From 12ecfd818448971ad9e731f5599d076cee63bbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 20 Sep 2022 23:22:32 +0200 Subject: [PATCH 001/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado --- .github/workflows/deploy.yml | 57 + README.md | 102 +- docusaurus.config.js | 4 +- setenv.sh | 18 +- ...aleTransaction.PNG => SaleTransaction.png} | Bin ...covery.PNG => SaleTransactionRecovery.png} | Bin static/img/{cloudpos.PNG => cloudpos.png} | Bin static/img/{cloudpos2.PNG => cloudpos2.png} | Bin static/img/{cloudpos3.PNG => cloudpos3.png} | Bin static/img/{cloudpos4.PNG => cloudpos4.png} | Bin static/img/{cloudpos5.PNG => cloudpos5.png} | Bin yarn.lock | 8247 +++++++++++++++++ 12 files changed, 8364 insertions(+), 64 deletions(-) create mode 100644 .github/workflows/deploy.yml rename static/img/{SaleTransaction.PNG => SaleTransaction.png} (100%) rename static/img/{SaleTransactionRecovery.PNG => SaleTransactionRecovery.png} (100%) rename static/img/{cloudpos.PNG => cloudpos.png} (100%) rename static/img/{cloudpos2.PNG => cloudpos2.png} (100%) rename static/img/{cloudpos3.PNG => cloudpos3.png} (100%) rename static/img/{cloudpos4.PNG => cloudpos4.png} (100%) rename static/img/{cloudpos5.PNG => cloudpos5.png} (100%) create mode 100644 yarn.lock diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..7f16916 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,57 @@ +name: Deploy to GitHub Pages + +on: + pull_request: + branches: [main, dev] + push: + branches: [main, dev] + +jobs: + test-deploy: + if: github.event_name != 'push' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: yarn + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Test build website + run: yarn build + deploy: + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: yarn + - uses: webfactory/ssh-agent@v0.5.0 + with: + ssh-private-key: ${{ secrets.CARD_PRESENT_DEV_PRIVATE_KEY }} + if: github.ref == 'refs/heads/main' + - uses: webfactory/ssh-agent@v0.5.0 + with: + ssh-private-key: ${{ secrets.CARD_PRESENT_DEV_PRIVATE_KEY }} + if: github.ref == 'refs/heads/dev' + - name: Deploy to GitHub Pages + env: + USE_SSH: true + run: | + git config --global user.email "actions@github.com" + git config --global user.name "gh-actions" + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + echo "Deploying to production" + ./setenv.sh prod + else + echo "Deploying to staging" + ./setenv.sh dev + fi + cat docusaurus.config.js + yarn install --frozen-lockfile + yarn deploy \ No newline at end of file diff --git a/README.md b/README.md index fad2922..2ea1165 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,34 @@ # Handpoint Documentation Website -This documentation website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. - -## Installation - -Docusaurus is essentially a set of npm packages. -To be able to build the documentation framework locally we need to have [Node.js](https://nodejs.org/en/download/) version 14.13 or above. - -It is also recommended, but not mandatory, to use [yarm](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable). +This is the source code for the [Handpoint Documentation website](https://developer.handpoint.com/). The site is built using [Docusaurus 2](https://docusaurus.io/). ## Local Development -In the root folder we must execute the following commands: +### Requirements -```console -npm run start -``` -or -```console -yarn start -``` -This command starts a local development server and opens up a browser window (by default localhost:3000). Most changes are reflected live without having to restart the server. - -## Build -Docusaurus is a modern static website generator so we need to build the website into a directory of static contents and put it on a web server so that it can be viewed. To build the website: +Docusaurus is essentially a set of npm packages. If you want to build the site locally, you will need to have [Node.js](https://nodejs.org/en/) version 18 or above installed. -```console -npm run build -``` -or +You'll also have to install [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable). -```console -yarn build -``` -**The search function will only work when this `build` command has been executed** +### Installation -When the build is done, you can to test your build locally using: +To install the dependencies, run: -```console -npm run serve +```bash +yarn install ``` +### Build and Run the Site locally -This command generates static content into the `build` directory and can be served using any static contents hosting service. - -## Deployment +In the root folder we must execute the following commands: ```console -GIT_USER= USE_SSH=true yarn deploy +yarn start ``` -If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. - +This command starts a local development server and opens up a browser window (by default localhost:3000). Most changes are reflected live without having to restart the server. -## Generate a new SDK version +## Generate a new SDK version Generate a new SDK version will autogenerate a folder with the docs that are currently in the selected folder. Command to create a new version of Android SDK (e.g. version 6.8.0) @@ -67,30 +42,41 @@ Automatically, it will create the new folder for this version (version-Android S **To see it published you have to stop docusaurus and start it again** +## Deployment -## See a preview version before publishing -It is possible to see the result of a preview version before publishing it. -This version will appear with the name of `Next`. +The deployment is done automatically with Github Actions. The workflow is defined in `.github/workflows/deploy.yml`: +- Every time a PR is merged to `dev` branch, changes are deployed to https://developer.handpoint.io +- Every time a PR is merged to `main` branch, changes are deployed to https://developer.handpoint.com -To do this, in the file `docusaurus.config.js` we must change the value of the boolean property `includeCurrentVersion` to `true`. +The property `includeCurrentVersion` in `docusaurus.config.js` is set to `true` for `dev` branch and `true` for `main` branch. This is done to avoid having unfinished releases in the production website. -The `includeCurrentVersion` property is located within the plugin `plugin-content-docs` of each module or SDK. +**IMPORTANT**: If you are about to release the doc for a new version, make sure you follow the steps in the section [Generate a new SDK version](#generate-a-new-sdk-version) before merging to `main` branch. -Example for Android case +More info about this CI/CD pipeline can be found [here](https://handpoint.atlassian.net/wiki/spaces/DP/pages/3598450735/Documentation+Site). -``` -[ - '@docusaurus/plugin-content-docs', - { - id: 'android', - includeCurrentVersion: true, - path: './android', - routeBasePath: 'android', - sidebarPath: require.resolve('./sidebarsAndroid.js'), - sidebarCollapsed: false - }, -], -``` +## CI/CD + +The documentation site consists of two [docusaurus](https://docusaurus.io/) instances: + +- [Card present documentation](https://developer.handpoint.com/) +- [Card not present documentation](https://developer-ecomm.handpoint.com/) + +The documentation site follows [Gitflow strategy](https://docs.google.com/document/d/1nRKUXhPKga-UJ-UxXKYdssa9rKlyClNRfxM6J4fw11s/edit#heading=h.wy5fcj5rh5j6). The `main` branch is the production branch and the `dev` branch is the development/staging branch. + +The `dev` branch is deployed to: + +- [https://developer.handpoint.io](https://developer.handpoint.io) +- [https://developer-ecomm.handpoint.io](https://developer-ecomm.handpoint.io) + +and the `main` branch is deployed to: + +- [https://developer.handpoint.com](https://developer.handpoint.com) +- [https://developer-ecomm.handpoint.com](https://developer-ecomm.handpoint.com) + +Documentation changes can be developed locally and tested in the staging environment before being released to production. +Every time we want to integrate changes from a feature branch to the `dev` branch, we have to create a PR. The PR will be reviewed by one of the team members and merged to `dev` branch. This will trigger a deployment to the staging environment (It can take up to 5 minutes to be deployed). + +If you are writing documentation for a new version, you have to follow the steps in the section [Generate a new SDK version](#generate-a-new-sdk-version) before merging to `main` branch. -**Docusaurus will most likely need to be restarted for these changes to take effect.** \ No newline at end of file +Once the changes are tested in the staging environment, another PR has to be created to merge the changes from `dev` branch to `main` branch. This PR will be reviewed by two team members and merged to `main` branch. This will trigger a deployment to the production environment (It can take up to 5 minutes to be deployed). \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index d391a91..dee3694 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -11,8 +11,8 @@ module.exports = { onBrokenMarkdownLinks: 'warn', favicon: '/img/favicon.png', organizationName: 'handpoint', // Usually your GitHub org/user name. - projectName: 'doc', // Usually your repo name. - deploymentBranch: 'gh-pages', + projectName: 'handpoint.github.io', // Usually your repo name. + deploymentBranch: 'main', themeConfig: { navbar: { style: 'dark', diff --git a/setenv.sh b/setenv.sh index 1a8e09a..9bd1b3f 100755 --- a/setenv.sh +++ b/setenv.sh @@ -1,9 +1,19 @@ #!/bin/bash if [[ $1 == 'prod' ]] then - sed -i '' 's/handpoint.io/handpoint.com/g' docusaurus.config.js - sed -i '' 's/handpoint.io/handpoint.com/g' src/pages/index.js + sed -i 's/handpoint.io/handpoint.com/g' docusaurus.config.js + sed -i "s/url: 'https://developer.handpoint.io'/url: 'https://developer.handpoint.io'/g" docusaurus.config.js + sed -i 's/includeCurrentVersion: true/includeCurrentVersion: false/g' docusaurus.config.js + sed -i "s/organizationName: 'handpoint'/organizationName: 'handpoint'/g" docusaurus.config.js + sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js + sed -i 's/handpoint.io/handpoint.com/g' src/pages/index.js + sed -i 's/developer.handpoint.com/developer.handpoint.com/g' static/CNAME else - sed -i '' 's/handpoint.com/handpoint.io/g' docusaurus.config.js - sed -i '' 's/handpoint.com/handpoint.io/g' src/pages/index.js + sed -i 's/handpoint.com/handpoint.io/g' docusaurus.config.js + sed -i "s/url: 'https://developer.handpoint.com'/url: 'https://developer.handpoint.io'/g" docusaurus.config.js + sed -i 's/includeCurrentVersion: false/includeCurrentVersion: true/g' docusaurus.config.js + sed -i "s/organizationName: 'handpoint'/organizationName: 'handpointdev'/g" docusaurus.config.js + sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js + sed -i 's/handpoint.com/handpoint.io/g' src/pages/index.js + sed -i 's/developer.handpoint.com/handpointdev.github.io/g' static/CNAME fi \ No newline at end of file diff --git a/static/img/SaleTransaction.PNG b/static/img/SaleTransaction.png similarity index 100% rename from static/img/SaleTransaction.PNG rename to static/img/SaleTransaction.png diff --git a/static/img/SaleTransactionRecovery.PNG b/static/img/SaleTransactionRecovery.png similarity index 100% rename from static/img/SaleTransactionRecovery.PNG rename to static/img/SaleTransactionRecovery.png diff --git a/static/img/cloudpos.PNG b/static/img/cloudpos.png similarity index 100% rename from static/img/cloudpos.PNG rename to static/img/cloudpos.png diff --git a/static/img/cloudpos2.PNG b/static/img/cloudpos2.png similarity index 100% rename from static/img/cloudpos2.PNG rename to static/img/cloudpos2.png diff --git a/static/img/cloudpos3.PNG b/static/img/cloudpos3.png similarity index 100% rename from static/img/cloudpos3.PNG rename to static/img/cloudpos3.png diff --git a/static/img/cloudpos4.PNG b/static/img/cloudpos4.png similarity index 100% rename from static/img/cloudpos4.PNG rename to static/img/cloudpos4.png diff --git a/static/img/cloudpos5.PNG b/static/img/cloudpos5.png similarity index 100% rename from static/img/cloudpos5.PNG rename to static/img/cloudpos5.png diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..6e13961 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,8247 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@algolia/autocomplete-core@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.1.tgz#025538b8a9564a9f3dd5bcf8a236d6951c76c7d1" + integrity sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg== + dependencies: + "@algolia/autocomplete-shared" "1.7.1" + +"@algolia/autocomplete-js@^1.5.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-js/-/autocomplete-js-1.7.1.tgz#4cb41eb916cc83d67a96294916ceb86c8200946e" + integrity sha512-m8xQiH1qdthovVOD9O8/ur9P5us+sljskIpB1HFQIFmsfchorJNFlpMT+zE8V55tbJOwusUrp85c9t+6lkOllg== + dependencies: + "@algolia/autocomplete-core" "1.7.1" + "@algolia/autocomplete-preset-algolia" "1.7.1" + "@algolia/autocomplete-shared" "1.7.1" + htm "^3.0.0" + preact "^10.0.0" + +"@algolia/autocomplete-preset-algolia@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.1.tgz#7dadc5607097766478014ae2e9e1c9c4b3f957c8" + integrity sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg== + dependencies: + "@algolia/autocomplete-shared" "1.7.1" + +"@algolia/autocomplete-shared@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.1.tgz#95c3a0b4b78858fed730cf9c755b7d1cd0c82c74" + integrity sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg== + +"@algolia/autocomplete-theme-classic@^1.5.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.7.1.tgz#90613ed21bcc7fdc13b579091352f20f0fe83843" + integrity sha512-Uh2AuRMjgbwCgOQX+oZQ5RIaqIDZ2os4EDZd3WClnIYQl03VTvSD/JRPmlz/+agWpfoN/fX8XvmLUGt/d4DbYg== + +"@algolia/cache-browser-local-storage@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.2.tgz#d5b1b90130ca87c6321de876e167df9ec6524936" + integrity sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA== + dependencies: + "@algolia/cache-common" "4.14.2" + +"@algolia/cache-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.2.tgz#b946b6103c922f0c06006fb6929163ed2c67d598" + integrity sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg== + +"@algolia/cache-in-memory@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.2.tgz#88e4a21474f9ac05331c2fa3ceb929684a395a24" + integrity sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ== + dependencies: + "@algolia/cache-common" "4.14.2" + +"@algolia/client-account@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.2.tgz#b76ac1ba9ea71e8c3f77a1805b48350dc0728a16" + integrity sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-analytics@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.2.tgz#ca04dcaf9a78ee5c92c5cb5e9c74cf031eb2f1fb" + integrity sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.2.tgz#e1324e167ffa8af60f3e8bcd122110fd0bfd1300" + integrity sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q== + dependencies: + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-personalization@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.2.tgz#656bbb6157a3dd1a4be7de65e457fda136c404ec" + integrity sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-search@4.14.2", "@algolia/client-search@^4.12.0": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.2.tgz#357bdb7e640163f0e33bad231dfcc21f67dc2e92" + integrity sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/events@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" + integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== + +"@algolia/logger-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.2.tgz#b74b3a92431f92665519d95942c246793ec390ee" + integrity sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA== + +"@algolia/logger-console@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.2.tgz#ec49cb47408f5811d4792598683923a800abce7b" + integrity sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g== + dependencies: + "@algolia/logger-common" "4.14.2" + +"@algolia/requester-browser-xhr@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.2.tgz#a2cd4d9d8d90d53109cc7f3682dc6ebf20f798f2" + integrity sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw== + dependencies: + "@algolia/requester-common" "4.14.2" + +"@algolia/requester-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.2.tgz#bc4e9e5ee16c953c0ecacbfb334a33c30c28b1a1" + integrity sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg== + +"@algolia/requester-node-http@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.2.tgz#7c1223a1785decaab1def64c83dade6bea45e115" + integrity sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg== + dependencies: + "@algolia/requester-common" "4.14.2" + +"@algolia/transporter@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.2.tgz#77c069047fb1a4359ee6a51f51829508e44a1e3d" + integrity sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ== + dependencies: + "@algolia/cache-common" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9" + integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg== + +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" + integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.18.5", "@babel/core@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b" + integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.19.0" + "@babel/helper-compilation-targets" "^7.19.1" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helpers" "^7.19.0" + "@babel/parser" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" + integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== + dependencies: + "@babel/types" "^7.19.0" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c" + integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg== + dependencies: + "@babel/compat-data" "^7.19.1" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" + integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.9" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== + dependencies: + "@babel/types" "^7.18.9" + +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" + integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" + integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== + dependencies: + "@babel/types" "^7.18.9" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" + integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== + +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" + integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.12.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.8", "@babel/parser@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c" + integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + +"@babel/plugin-proposal-async-generator-functions@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" + integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + +"@babel/plugin-proposal-object-rest-spread@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" + integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q== + dependencies: + "@babel/compat-data" "^7.18.8" + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.18.8" + +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" + integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d" + integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-classes@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" + integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.19.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-replace-supers" "^7.18.9" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-destructuring@^7.18.13": + version "7.18.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" + integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-duplicate-keys@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + dependencies: + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-amd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21" + integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" + integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" + integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== + dependencies: + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-identifier" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" + integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-constant-elements@^7.17.12": + version "7.18.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.18.12.tgz#edf3bec47eb98f14e84fa0af137fcc6aad8e0443" + integrity sha512-Q99U9/ttiu+LMnRU8psd23HhvwXmKWDQIpocm0JKaICcZHnw+mdQbHm6xnSy7dOl8I5PELakYtNBubNQlBXbZw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" + +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + regenerator-transform "^0.15.0" + +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-runtime@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.1.tgz#a3df2d7312eea624c7889a2dcd37fd1dfd25b2c6" + integrity sha512-2nJjTUFIzBMP/f/miLxEK9vxwW/KUXsdvN4sR//TmuDhe6yU2h57WmIOE12Gng3MDP/xpjUV/ToZRdcf8Yj4fA== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + semver "^6.3.0" + +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typeof-symbol@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typescript@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.1.tgz#adcf180a041dcbd29257ad31b0c65d4de531ce8d" + integrity sha512-+ILcOU+6mWLlvCwnL920m2Ow3wWx3Wo8n2t5aROQmV55GZt+hOiLvBaa3DNzRjSEHa1aauRs4/YLmkCfFkhhRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-typescript" "^7.18.6" + +"@babel/plugin-transform-unicode-escapes@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.18.2", "@babel/preset-env@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67" + integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA== + dependencies: + "@babel/compat-data" "^7.19.1" + "@babel/helper-compilation-targets" "^7.19.1" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-async-generator-functions" "^7.19.1" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.9" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.18.9" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.18.9" + "@babel/plugin-transform-classes" "^7.19.0" + "@babel/plugin-transform-computed-properties" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.18.13" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.9" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.8" + "@babel/plugin-transform-function-name" "^7.18.9" + "@babel/plugin-transform-literals" "^7.18.9" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.18.6" + "@babel/plugin-transform-modules-commonjs" "^7.18.6" + "@babel/plugin-transform-modules-systemjs" "^7.19.0" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.18.8" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.19.0" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.9" + "@babel/plugin-transform-typeof-symbol" "^7.18.9" + "@babel/plugin-transform-unicode-escapes" "^7.18.10" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.19.0" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + core-js-compat "^3.25.1" + semver "^6.3.0" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.17.12", "@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/preset-typescript@^7.17.12", "@babel/preset-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/runtime-corejs3@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz#f0cbbe7edda7c4109cd253bb1dee99aba4594ad9" + integrity sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g== + dependencies: + core-js-pure "^3.25.1" + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.19.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.12.7", "@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347" + integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.19.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.19.1" + "@babel/types" "^7.19.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.12.7", "@babel/types@^7.18.10", "@babel/types@^7.18.4", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" + integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== + dependencies: + "@babel/helper-string-parser" "^7.18.10" + "@babel/helper-validator-identifier" "^7.18.6" + to-fast-properties "^2.0.0" + +"@cmfcmf/docusaurus-search-local@^0.9.4": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-0.9.4.tgz#2e87e4f1e9f05636b64a9f7ed50a5fe8116bafb4" + integrity sha512-OuW+wQrBn4cxpHS/jU0xC5F1IVY1NTPx53qMuwGGwQvomMr5bcot79ifX5O1rwALRJW7DnKh5axQI6K+jI241Q== + dependencies: + "@algolia/autocomplete-js" "^1.5.1" + "@algolia/autocomplete-theme-classic" "^1.5.1" + "@algolia/client-search" "^4.12.0" + algoliasearch "^4.12.0" + cheerio "^1.0.0-rc.9" + clsx "^1.1.1" + lunr-languages "^1.4.0" + mark.js "^8.11.1" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@docsearch/css@3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.2.1.tgz#c05d7818b0e43b42f9efa2d82a11c36606b37b27" + integrity sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g== + +"@docsearch/react@^3.1.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.2.1.tgz#112ad88db07367fa6fd933d67d58421d8d8289aa" + integrity sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ== + dependencies: + "@algolia/autocomplete-core" "1.7.1" + "@algolia/autocomplete-preset-algolia" "1.7.1" + "@docsearch/css" "3.2.1" + algoliasearch "^4.0.0" + +"@docusaurus/core@2.1.0", "@docusaurus/core@^2.0.0-beta.21": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.1.0.tgz#4aedc306f4c4cd2e0491b641bf78941d4b480ab6" + integrity sha512-/ZJ6xmm+VB9Izbn0/s6h6289cbPy2k4iYFwWDhjiLsVqwa/Y0YBBcXvStfaHccudUC3OfP+26hMk7UCjc50J6Q== + dependencies: + "@babel/core" "^7.18.6" + "@babel/generator" "^7.18.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-runtime" "^7.18.6" + "@babel/preset-env" "^7.18.6" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@babel/runtime" "^7.18.6" + "@babel/runtime-corejs3" "^7.18.6" + "@babel/traverse" "^7.18.8" + "@docusaurus/cssnano-preset" "2.1.0" + "@docusaurus/logger" "2.1.0" + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-common" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + "@slorber/static-site-generator-webpack-plugin" "^4.0.7" + "@svgr/webpack" "^6.2.1" + autoprefixer "^10.4.7" + babel-loader "^8.2.5" + babel-plugin-dynamic-import-node "^2.3.3" + boxen "^6.2.1" + chalk "^4.1.2" + chokidar "^3.5.3" + clean-css "^5.3.0" + cli-table3 "^0.6.2" + combine-promises "^1.1.0" + commander "^5.1.0" + copy-webpack-plugin "^11.0.0" + core-js "^3.23.3" + css-loader "^6.7.1" + css-minimizer-webpack-plugin "^4.0.0" + cssnano "^5.1.12" + del "^6.1.1" + detect-port "^1.3.0" + escape-html "^1.0.3" + eta "^1.12.3" + file-loader "^6.2.0" + fs-extra "^10.1.0" + html-minifier-terser "^6.1.0" + html-tags "^3.2.0" + html-webpack-plugin "^5.5.0" + import-fresh "^3.3.0" + leven "^3.1.0" + lodash "^4.17.21" + mini-css-extract-plugin "^2.6.1" + postcss "^8.4.14" + postcss-loader "^7.0.0" + prompts "^2.4.2" + react-dev-utils "^12.0.1" + react-helmet-async "^1.3.0" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + react-loadable-ssr-addon-v5-slorber "^1.0.1" + react-router "^5.3.3" + react-router-config "^5.1.1" + react-router-dom "^5.3.3" + rtl-detect "^1.0.4" + semver "^7.3.7" + serve-handler "^6.1.3" + shelljs "^0.8.5" + terser-webpack-plugin "^5.3.3" + tslib "^2.4.0" + update-notifier "^5.1.0" + url-loader "^4.1.1" + wait-on "^6.0.1" + webpack "^5.73.0" + webpack-bundle-analyzer "^4.5.0" + webpack-dev-server "^4.9.3" + webpack-merge "^5.8.0" + webpackbar "^5.0.2" + +"@docusaurus/cssnano-preset@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.1.0.tgz#5b42107769b7cbc61655496090bc262d7788d6ab" + integrity sha512-pRLewcgGhOies6pzsUROfmPStDRdFw+FgV5sMtLr5+4Luv2rty5+b/eSIMMetqUsmg3A9r9bcxHk9bKAKvx3zQ== + dependencies: + cssnano-preset-advanced "^5.3.8" + postcss "^8.4.14" + postcss-sort-media-queries "^4.2.1" + tslib "^2.4.0" + +"@docusaurus/logger@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.1.0.tgz#86c97e948f578814d3e61fc2b2ad283043cbe87a" + integrity sha512-uuJx2T6hDBg82joFeyobywPjSOIfeq05GfyKGHThVoXuXsu1KAzMDYcjoDxarb9CoHCI/Dor8R2MoL6zII8x1Q== + dependencies: + chalk "^4.1.2" + tslib "^2.4.0" + +"@docusaurus/mdx-loader@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.1.0.tgz#3fca9576cc73a22f8e7d9941985590b9e47a8526" + integrity sha512-i97hi7hbQjsD3/8OSFhLy7dbKGH8ryjEzOfyhQIn2CFBYOY3ko0vMVEf3IY9nD3Ld7amYzsZ8153RPkcnXA+Lg== + dependencies: + "@babel/parser" "^7.18.8" + "@babel/traverse" "^7.18.8" + "@docusaurus/logger" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@mdx-js/mdx" "^1.6.22" + escape-html "^1.0.3" + file-loader "^6.2.0" + fs-extra "^10.1.0" + image-size "^1.0.1" + mdast-util-to-string "^2.0.0" + remark-emoji "^2.2.0" + stringify-object "^3.3.0" + tslib "^2.4.0" + unified "^9.2.2" + unist-util-visit "^2.0.3" + url-loader "^4.1.1" + webpack "^5.73.0" + +"@docusaurus/module-type-aliases@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.1.0.tgz#322f8fd5b436af2154c0dddfa173435730e66261" + integrity sha512-Z8WZaK5cis3xEtyfOT817u9xgGUauT0PuuVo85ysnFRX8n7qLN1lTPCkC+aCmFm/UcV8h/W5T4NtIsst94UntQ== + dependencies: + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/types" "2.1.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + "@types/react-router-dom" "*" + react-helmet-async "*" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + +"@docusaurus/plugin-content-blog@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.1.0.tgz#32b1a7cd4b0026f4a76fce4edc5cfdd0edb1ec42" + integrity sha512-xEp6jlu92HMNUmyRBEeJ4mCW1s77aAEQO4Keez94cUY/Ap7G/r0Awa6xSLff7HL0Fjg8KK1bEbDy7q9voIavdg== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/logger" "2.1.0" + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-common" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + cheerio "^1.0.0-rc.12" + feed "^4.2.2" + fs-extra "^10.1.0" + lodash "^4.17.21" + reading-time "^1.5.0" + tslib "^2.4.0" + unist-util-visit "^2.0.3" + utility-types "^3.10.0" + webpack "^5.73.0" + +"@docusaurus/plugin-content-docs@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.1.0.tgz#3fcdf258c13dde27268ce7108a102b74ca4c279b" + integrity sha512-Rup5pqXrXlKGIC4VgwvioIhGWF7E/NNSlxv+JAxRYpik8VKlWsk9ysrdHIlpX+KJUCO9irnY21kQh2814mlp/Q== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/logger" "2.1.0" + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/module-type-aliases" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + "@types/react-router-config" "^5.0.6" + combine-promises "^1.1.0" + fs-extra "^10.1.0" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + lodash "^4.17.21" + tslib "^2.4.0" + utility-types "^3.10.0" + webpack "^5.73.0" + +"@docusaurus/plugin-content-pages@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.1.0.tgz#714d24f71d49dbfed888f50c15e975c2154c3ce8" + integrity sha512-SwZdDZRlObHNKXTnFo7W2aF6U5ZqNVI55Nw2GCBryL7oKQSLeI0lsrMlMXdzn+fS7OuBTd3MJBO1T4Zpz0i/+g== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + fs-extra "^10.1.0" + tslib "^2.4.0" + webpack "^5.73.0" + +"@docusaurus/plugin-debug@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.1.0.tgz#b3145affb40e25cf342174638952a5928ddaf7dc" + integrity sha512-8wsDq3OIfiy6440KLlp/qT5uk+WRHQXIXklNHEeZcar+Of0TZxCNe2FBpv+bzb/0qcdP45ia5i5WmR5OjN6DPw== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + fs-extra "^10.1.0" + react-json-view "^1.21.3" + tslib "^2.4.0" + +"@docusaurus/plugin-google-analytics@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.1.0.tgz#c9a7269817b38e43484d38fad9996e39aac4196c" + integrity sha512-4cgeqIly/wcFVbbWP03y1QJJBgH8W+Bv6AVbWnsXNOZa1yB3AO6hf3ZdeQH9x20v9T2pREogVgAH0rSoVnNsgg== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + tslib "^2.4.0" + +"@docusaurus/plugin-google-gtag@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.1.0.tgz#e4f351dcd98b933538d55bb742650a2a36ca9a32" + integrity sha512-/3aDlv2dMoCeiX2e+DTGvvrdTA+v3cKQV3DbmfsF4ENhvc5nKV23nth04Z3Vq0Ci1ui6Sn80TkhGk/tiCMW2AA== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + tslib "^2.4.0" + +"@docusaurus/plugin-sitemap@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.1.0.tgz#b316bb9a42a1717845e26bd4e2d3071748a54b47" + integrity sha512-2Y6Br8drlrZ/jN9MwMBl0aoi9GAjpfyfMBYpaQZXimbK+e9VjYnujXlvQ4SxtM60ASDgtHIAzfVFBkSR/MwRUw== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/logger" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-common" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + fs-extra "^10.1.0" + sitemap "^7.1.1" + tslib "^2.4.0" + +"@docusaurus/preset-classic@^2.0.0-beta.21": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.1.0.tgz#45b23c8ec10c96ded9ece128fac3a39b10bcbc56" + integrity sha512-NQMnaq974K4BcSMXFSJBQ5itniw6RSyW+VT+6i90kGZzTwiuKZmsp0r9lC6BYAvvVMQUNJQwrETmlu7y2XKW7w== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/plugin-content-blog" "2.1.0" + "@docusaurus/plugin-content-docs" "2.1.0" + "@docusaurus/plugin-content-pages" "2.1.0" + "@docusaurus/plugin-debug" "2.1.0" + "@docusaurus/plugin-google-analytics" "2.1.0" + "@docusaurus/plugin-google-gtag" "2.1.0" + "@docusaurus/plugin-sitemap" "2.1.0" + "@docusaurus/theme-classic" "2.1.0" + "@docusaurus/theme-common" "2.1.0" + "@docusaurus/theme-search-algolia" "2.1.0" + "@docusaurus/types" "2.1.0" + +"@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz#81aae0db81ecafbdaee3651f12804580868fa6ce" + integrity sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ== + dependencies: + "@types/react" "*" + prop-types "^15.6.2" + +"@docusaurus/theme-classic@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.1.0.tgz#d957a907ea8dd035c1cf911d0fbe91d8f24aef3f" + integrity sha512-xn8ZfNMsf7gaSy9+ClFnUu71o7oKgMo5noYSS1hy3svNifRTkrBp6+MReLDsmIaj3mLf2e7+JCBYKBFbaGzQng== + dependencies: + "@docusaurus/core" "2.1.0" + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/module-type-aliases" "2.1.0" + "@docusaurus/plugin-content-blog" "2.1.0" + "@docusaurus/plugin-content-docs" "2.1.0" + "@docusaurus/plugin-content-pages" "2.1.0" + "@docusaurus/theme-common" "2.1.0" + "@docusaurus/theme-translations" "2.1.0" + "@docusaurus/types" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-common" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + "@mdx-js/react" "^1.6.22" + clsx "^1.2.1" + copy-text-to-clipboard "^3.0.1" + infima "0.2.0-alpha.42" + lodash "^4.17.21" + nprogress "^0.2.0" + postcss "^8.4.14" + prism-react-renderer "^1.3.5" + prismjs "^1.28.0" + react-router-dom "^5.3.3" + rtlcss "^3.5.0" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-common@2.1.0", "@docusaurus/theme-common@^2.0.0-beta.20": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.1.0.tgz#dff4d5d1e29efc06125dc06f7b259f689bb3f24d" + integrity sha512-vT1otpVPbKux90YpZUnvknsn5zvpLf+AW1W0EDcpE9up4cDrPqfsh0QoxGHFJnobE2/qftsBFC19BneN4BH8Ag== + dependencies: + "@docusaurus/mdx-loader" "2.1.0" + "@docusaurus/module-type-aliases" "2.1.0" + "@docusaurus/plugin-content-blog" "2.1.0" + "@docusaurus/plugin-content-docs" "2.1.0" + "@docusaurus/plugin-content-pages" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + clsx "^1.2.1" + parse-numeric-range "^1.3.0" + prism-react-renderer "^1.3.5" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-search-algolia@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.1.0.tgz#e7cdf64b6f7a15b07c6dcf652fd308cfdaabb0ee" + integrity sha512-rNBvi35VvENhucslEeVPOtbAzBdZY/9j55gdsweGV5bYoAXy4mHB6zTGjealcB4pJ6lJY4a5g75fXXMOlUqPfg== + dependencies: + "@docsearch/react" "^3.1.1" + "@docusaurus/core" "2.1.0" + "@docusaurus/logger" "2.1.0" + "@docusaurus/plugin-content-docs" "2.1.0" + "@docusaurus/theme-common" "2.1.0" + "@docusaurus/theme-translations" "2.1.0" + "@docusaurus/utils" "2.1.0" + "@docusaurus/utils-validation" "2.1.0" + algoliasearch "^4.13.1" + algoliasearch-helper "^3.10.0" + clsx "^1.2.1" + eta "^1.12.3" + fs-extra "^10.1.0" + lodash "^4.17.21" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-translations@2.1.0", "@docusaurus/theme-translations@^2.0.0-beta.20": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.1.0.tgz#ce9a2955afd49bff364cfdfd4492b226f6dd3b6e" + integrity sha512-07n2akf2nqWvtJeMy3A+7oSGMuu5F673AovXVwY0aGAux1afzGCiqIFlYW3EP0CujvDJAEFSQi/Tetfh+95JNg== + dependencies: + fs-extra "^10.1.0" + tslib "^2.4.0" + +"@docusaurus/types@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.1.0.tgz#01e13cd9adb268fffe87b49eb90302d5dc3edd6b" + integrity sha512-BS1ebpJZnGG6esKqsjtEC9U9qSaPylPwlO7cQ1GaIE7J/kMZI3FITnNn0otXXu7c7ZTqhb6+8dOrG6fZn6fqzQ== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + commander "^5.1.0" + joi "^17.6.0" + react-helmet-async "^1.3.0" + utility-types "^3.10.0" + webpack "^5.73.0" + webpack-merge "^5.8.0" + +"@docusaurus/utils-common@2.1.0", "@docusaurus/utils-common@^2.0.0-beta.20": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.1.0.tgz#248434751096f8c6c644ed65eed2a5a070a227f8" + integrity sha512-F2vgmt4yRFgRQR2vyEFGTWeyAdmgKbtmu3sjHObF0tjjx/pN0Iw/c6eCopaH34E6tc9nO0nvp01pwW+/86d1fg== + dependencies: + tslib "^2.4.0" + +"@docusaurus/utils-validation@2.1.0", "@docusaurus/utils-validation@^2.0.0-beta.20": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.1.0.tgz#c8cf1d8454d924d9a564fefa86436268f43308e3" + integrity sha512-AMJzWYKL3b7FLltKtDXNLO9Y649V2BXvrnRdnW2AA+PpBnYV78zKLSCz135cuWwRj1ajNtP4onbXdlnyvCijGQ== + dependencies: + "@docusaurus/logger" "2.1.0" + "@docusaurus/utils" "2.1.0" + joi "^17.6.0" + js-yaml "^4.1.0" + tslib "^2.4.0" + +"@docusaurus/utils@2.1.0", "@docusaurus/utils@^2.0.0-beta.20": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.1.0.tgz#b77b45b22e61eb6c2dcad8a7e96f6db0409b655f" + integrity sha512-fPvrfmAuC54n8MjZuG4IysaMdmvN5A/qr7iFLbSGSyDrsbP4fnui6KdZZIa/YOLIPLec8vjZ8RIITJqF18mx4A== + dependencies: + "@docusaurus/logger" "2.1.0" + "@svgr/webpack" "^6.2.1" + file-loader "^6.2.0" + fs-extra "^10.1.0" + github-slugger "^1.4.0" + globby "^11.1.0" + gray-matter "^4.0.3" + js-yaml "^4.1.0" + lodash "^4.17.21" + micromatch "^4.0.5" + resolve-pathname "^3.0.0" + shelljs "^0.8.5" + tslib "^2.4.0" + url-loader "^4.1.1" + webpack "^5.73.0" + +"@easyops-cn/autocomplete.js@^0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@easyops-cn/autocomplete.js/-/autocomplete.js-0.38.1.tgz#46dff5795a9a032fa9b9250fdf63ca6c61c07629" + integrity sha512-drg76jS6syilOUmVNkyo1c7ZEBPcPuK+aJA7AksM5ZIIbV57DMHCywiCr+uHyv8BE5jUTU98j/H7gVrkHrWW3Q== + dependencies: + cssesc "^3.0.0" + immediate "^3.2.3" + +"@easyops-cn/docusaurus-search-local@^0.26.1": + version "0.26.1" + resolved "https://registry.yarnpkg.com/@easyops-cn/docusaurus-search-local/-/docusaurus-search-local-0.26.1.tgz#a2d00e4f7ce4aaf44d31ef3adc6396d690186578" + integrity sha512-cX/A7+3YUmR3Az6FCpIzx7seOzcTHk6ufmr8LqewDINDzh/2rYrBDNmBi+UZvYKshG+HyEkrp9ViHzJImec8BQ== + dependencies: + "@docusaurus/theme-common" "^2.0.0-beta.20" + "@docusaurus/theme-translations" "^2.0.0-beta.20" + "@docusaurus/utils" "^2.0.0-beta.20" + "@docusaurus/utils-common" "^2.0.0-beta.20" + "@docusaurus/utils-validation" "^2.0.0-beta.20" + "@easyops-cn/autocomplete.js" "^0.38.1" + "@node-rs/jieba" "^1.6.0" + cheerio "^1.0.0-rc.3" + clsx "^1.1.1" + debug "^4.2.0" + fs-extra "^10.0.0" + klaw-sync "^6.0.0" + lunr "^2.3.9" + lunr-languages "^1.4.0" + mark.js "^8.11.1" + tslib "^2.4.0" + +"@emotion/babel-plugin@^11.10.0": + version "11.10.2" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz#879db80ba622b3f6076917a1e6f648b1c7d008c7" + integrity sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.17.12" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/serialize" "^1.1.0" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.0.13" + +"@emotion/cache@^11.10.0", "@emotion/cache@^11.10.3": + version "11.10.3" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.3.tgz#c4f67904fad10c945fea5165c3a5a0583c164b87" + integrity sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ== + dependencies: + "@emotion/memoize" "^0.8.0" + "@emotion/sheet" "^1.2.0" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" + stylis "4.0.13" + +"@emotion/hash@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" + integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== + +"@emotion/is-prop-valid@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" + integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== + dependencies: + "@emotion/memoize" "^0.8.0" + +"@emotion/memoize@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" + integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== + +"@emotion/react@^11.7.1": + version "11.10.4" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.4.tgz#9dc6bccbda5d70ff68fdb204746c0e8b13a79199" + integrity sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.10.0" + "@emotion/cache" "^11.10.0" + "@emotion/serialize" "^1.1.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8" + integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA== + dependencies: + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/unitless" "^0.8.0" + "@emotion/utils" "^1.2.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5" + integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w== + +"@emotion/styled@^11.6.0": + version "11.10.4" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.4.tgz#e93f84a4d54003c2acbde178c3f97b421fce1cd4" + integrity sha512-pRl4R8Ez3UXvOPfc2bzIoV8u9P97UedgHS4FPX594ntwEuAMA114wlaHvOK24HB48uqfXiGlYIZYCxVJ1R1ttQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.10.0" + "@emotion/is-prop-valid" "^1.2.0" + "@emotion/serialize" "^1.1.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" + "@emotion/utils" "^1.2.0" + +"@emotion/unitless@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" + integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df" + integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A== + +"@emotion/utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" + integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== + +"@emotion/weak-memoize@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" + integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== + +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@mdx-js/mdx@^1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" + integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== + dependencies: + "@babel/core" "7.12.9" + "@babel/plugin-syntax-jsx" "7.12.1" + "@babel/plugin-syntax-object-rest-spread" "7.8.3" + "@mdx-js/util" "1.6.22" + babel-plugin-apply-mdx-type-prop "1.6.22" + babel-plugin-extract-import-names "1.6.22" + camelcase-css "2.0.1" + detab "2.0.4" + hast-util-raw "6.0.1" + lodash.uniq "4.5.0" + mdast-util-to-hast "10.0.1" + remark-footnotes "2.0.0" + remark-mdx "1.6.22" + remark-parse "8.0.3" + remark-squeeze-paragraphs "4.0.0" + style-to-object "0.3.0" + unified "9.2.0" + unist-builder "2.0.3" + unist-util-visit "2.0.3" + +"@mdx-js/react@^1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" + integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== + +"@mdx-js/util@1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" + integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== + +"@mui/base@5.0.0-alpha.98": + version "5.0.0-alpha.98" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.98.tgz#d1c89477d74cbfc64a7d1b336a6dbe83d4057ee8" + integrity sha512-c0U51+K2m57MASpRrmNs6qTXSvktDbVcSjD8zCRPbfuwYWERGGwNxwM3/jsBa4dSojTSmLPnOBFDypl74Ds6yQ== + dependencies: + "@babel/runtime" "^7.19.0" + "@emotion/is-prop-valid" "^1.2.0" + "@mui/types" "^7.2.0" + "@mui/utils" "^5.10.6" + "@popperjs/core" "^2.11.6" + clsx "^1.2.1" + prop-types "^15.8.1" + react-is "^18.2.0" + +"@mui/core-downloads-tracker@^5.10.6": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.6.tgz#dd17d976a47950e7bde5bcabf52f3253ce6d62a1" + integrity sha512-dmyQBqrKmVU6yCSM4GGal5qNXpViXX+/V1t0GA1A5i9QF5Gx6noV/cw0hrSS2ffLT8L2oScq1oTdA6NVIiQ8lg== + +"@mui/material@^5.3.1": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.10.6.tgz#46d04b5dd79fe83bdab5322301db1008e0d7c0e3" + integrity sha512-QilW5PAAGSQdN7Cpp4rwSQ1doJAt3ca1a2PHZtr8RLVlpHnXb+qQ8CeDo9+9V2fK5CDNdtTN1F+iJKO43aFBpQ== + dependencies: + "@babel/runtime" "^7.19.0" + "@mui/base" "5.0.0-alpha.98" + "@mui/core-downloads-tracker" "^5.10.6" + "@mui/system" "^5.10.6" + "@mui/types" "^7.2.0" + "@mui/utils" "^5.10.6" + "@types/react-transition-group" "^4.4.5" + clsx "^1.2.1" + csstype "^3.1.0" + prop-types "^15.8.1" + react-is "^18.2.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^5.10.6": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.10.6.tgz#2c6bb2a4b7034cd402a099bd0349f217584e7b25" + integrity sha512-I/W0QyTLRdEx6py3lKAquKO/rNF/7j+nIOM/xCyI9kU0fcotVTcTY08mKMsS6vrzdWpi6pAkD0wP0KwWy5R5VA== + dependencies: + "@babel/runtime" "^7.19.0" + "@mui/utils" "^5.10.6" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.10.6": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.10.6.tgz#9c6e79b29740e9f494c9fb26ebd4046aa88c1d21" + integrity sha512-OnVw5xnO4l0XzlJFhKif/RlLenBNhyEQQlSTwB9ApSWB05UAU5ZSbjNsRfyEKvgmQ/fPa+MqPD/dzxbIRCwyeg== + dependencies: + "@babel/runtime" "^7.19.0" + "@emotion/cache" "^11.10.3" + csstype "^3.1.0" + prop-types "^15.8.1" + +"@mui/system@^5.10.6": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.10.6.tgz#ddeeb63830e325a06ba8a0cf33ec950c49a06a73" + integrity sha512-HfQVX7e2xpQ3jtdB/WwtkFVtozMOozyN575/63u8ILHkE8wGDhblmCieAsnyJPFbm7WBW5PCMyzmfr4QyKLaYg== + dependencies: + "@babel/runtime" "^7.19.0" + "@mui/private-theming" "^5.10.6" + "@mui/styled-engine" "^5.10.6" + "@mui/types" "^7.2.0" + "@mui/utils" "^5.10.6" + clsx "^1.2.1" + csstype "^3.1.0" + prop-types "^15.8.1" + +"@mui/types@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.0.tgz#91380c2d42420f51f404120f7a9270eadd6f5c23" + integrity sha512-lGXtFKe5lp3UxTBGqKI1l7G8sE2xBik8qCfrLHD5olwP/YU0/ReWoWT7Lp1//ri32dK39oPMrJN8TgbkCSbsNA== + +"@mui/utils@^5.10.6": + version "5.10.6" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.10.6.tgz#98d432d2b05544c46efe356cf095cea3a37c2e59" + integrity sha512-g0Qs8xN/MW2M3fLL8197h5J2VB9U+49fLlnKKqC6zy/yus5cZwdT+Gwec+wUMxgwQoxMDn+J8oDWAn28kEOR/Q== + dependencies: + "@babel/runtime" "^7.19.0" + "@types/prop-types" "^15.7.5" + "@types/react-is" "^16.7.1 || ^17.0.0" + prop-types "^15.8.1" + react-is "^18.2.0" + +"@node-rs/jieba-android-arm-eabi@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-android-arm-eabi/-/jieba-android-arm-eabi-1.6.1.tgz#196f1052a564d2608e46c87114aa78232453b798" + integrity sha512-R1YQfsPr7sK3Tq1sM0//6lNAGJK9RnMT0ShITT+7EJYr5OufUBb38lf/mRhrLxR0NF1pycEsMjdCAwrWrHd8rA== + +"@node-rs/jieba-android-arm64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-android-arm64/-/jieba-android-arm64-1.6.1.tgz#cb4db38d9fcb877ac06659281a2dc5f50fe7be52" + integrity sha512-hBRbj2uLmRFYDw2lWppTAPoyjeXkBKUT84h4fHUQj7CMU94Gc1IWkE4ocCqhvUhbaUXlCpocS9mB0/fc2641bw== + +"@node-rs/jieba-darwin-arm64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-darwin-arm64/-/jieba-darwin-arm64-1.6.1.tgz#83ad4bddd9368556ccd46555a508abbf9007fa4b" + integrity sha512-GeoDe7XVTF6z8JUtD98QvwudsMaHV5EBXs5uO43SobeIkShH3Nujq5gLMD5kWoJXTxDrTgJe4wT42EwUaBEH2Q== + +"@node-rs/jieba-darwin-x64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-darwin-x64/-/jieba-darwin-x64-1.6.1.tgz#ddd964b7874c208b964897898c5826ef195efcad" + integrity sha512-ENHYIS8b8JdMaUXEm0f8Y3+sHXu2UdukG1D/XGUNx+q5cn07HbwIg6L0tlGhE8dw4AhqoWHsExVaZ241Igh4iA== + +"@node-rs/jieba-freebsd-x64@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-freebsd-x64/-/jieba-freebsd-x64-1.6.1.tgz#8e8be576d471c0837dcf4a6130ab055cca588e80" + integrity sha512-chwB/9edtxqS8Jm3j4RMaJjH9AlXmijUgKv02oMw36e77HKpko+tENUN25Vrn/9GKsKGqIPeXpmCjeXCN1HVQA== + +"@node-rs/jieba-linux-arm-gnueabihf@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm-gnueabihf/-/jieba-linux-arm-gnueabihf-1.6.1.tgz#be1c7205f0ecf03f8f9065ad60b58bb4f7615d71" + integrity sha512-tsb5fMGj4p8bHGfkf7bJ+HE2jxaixLTp3YnGg5D+kp8+HQRq8cp3ScG5cn8cq0phnJS/zfAp8rVfWInDagzKKQ== + +"@node-rs/jieba-linux-arm64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm64-gnu/-/jieba-linux-arm64-gnu-1.6.1.tgz#43608a4506f6b47bec3349312a18c1a51b6f3822" + integrity sha512-bSInORkJFfeZNR+i4rFoSZGbwkQtQlnZ0XfT/noTK9JUBDYErqQZPFjoaYAU45NWTk7p6Zkg30SuV1NTdWLaPw== + +"@node-rs/jieba-linux-arm64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-arm64-musl/-/jieba-linux-arm64-musl-1.6.1.tgz#aef63ab32d3caa4ab7cc0f717dd7a6e774083b9b" + integrity sha512-qphL6xM7owfU8Hsh7GX73SDr/iApbnc+35mSLxbibAfCQnY89+WcBeWUUOSGM/Ov3VFaq4pyVlDFj0YjR01W2w== + +"@node-rs/jieba-linux-x64-gnu@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-x64-gnu/-/jieba-linux-x64-gnu-1.6.1.tgz#8e09bb2c57fc546acc9cf8e1c879dcdf01e79717" + integrity sha512-f6hhlrbi2wel0xZG7m3Wvksimt9MSu1f3aYO2Kwavf4qjMRZqJzLz9HlCJAal6AXB9Qgg+685P+gftsWve47qw== + +"@node-rs/jieba-linux-x64-musl@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-linux-x64-musl/-/jieba-linux-x64-musl-1.6.1.tgz#f698db4b49cfd367b5c3f6b4352d5092ab3620e2" + integrity sha512-cTVcdR6zWqpnmdEUyWEII9zfE5lTeWN53TbiOPx8TCA+291/31Vqd7GA8YEPndUO8qgCx5uShSDFStBAEIhYNQ== + +"@node-rs/jieba-win32-arm64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-arm64-msvc/-/jieba-win32-arm64-msvc-1.6.1.tgz#43a20ca596eac90659a64721f0ad2130b2be199e" + integrity sha512-YuOTrjHazDraXcGXRHgPQ53nyJuH8QtTCngYKjAzxsdt8uN+txb1AY69OLMLBBZqLTOwY9dgcW70vGiLQMCTeg== + +"@node-rs/jieba-win32-ia32-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-ia32-msvc/-/jieba-win32-ia32-msvc-1.6.1.tgz#eec9062cdc5dd951f7177576993bbc32fa405416" + integrity sha512-4+E843ImGpVlZ+LlT9E/13NHmmUg3UHQx419D6fFMorJUUQuK4cZJfE1z4tCgcrbV8S5Wew5LIFywlJeJLu0LQ== + +"@node-rs/jieba-win32-x64-msvc@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba-win32-x64-msvc/-/jieba-win32-x64-msvc-1.6.1.tgz#3df4853afc175e4dd43794b08a71e8d25d00e807" + integrity sha512-veXNwm2VlseOzl7vaC7A/nZ4okp5/6edN7/Atj6mXnUbze/m/my5Rv5zUcW3U1D9VElnQ3srCHCa5vXljJuk6g== + +"@node-rs/jieba@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@node-rs/jieba/-/jieba-1.6.1.tgz#221aa586aa671cb029687256a4c86c86bfecbef9" + integrity sha512-pISKu8NIYKRvZp7mhYZYA8VCjJMqTsCe+mQcFFnAi3GNJsijGjef2peMFeDcvP72X8MsnNeYeg3rHkAybtefyQ== + optionalDependencies: + "@node-rs/jieba-android-arm-eabi" "1.6.1" + "@node-rs/jieba-android-arm64" "1.6.1" + "@node-rs/jieba-darwin-arm64" "1.6.1" + "@node-rs/jieba-darwin-x64" "1.6.1" + "@node-rs/jieba-freebsd-x64" "1.6.1" + "@node-rs/jieba-linux-arm-gnueabihf" "1.6.1" + "@node-rs/jieba-linux-arm64-gnu" "1.6.1" + "@node-rs/jieba-linux-arm64-musl" "1.6.1" + "@node-rs/jieba-linux-x64-gnu" "1.6.1" + "@node-rs/jieba-linux-x64-musl" "1.6.1" + "@node-rs/jieba-win32-arm64-msvc" "1.6.1" + "@node-rs/jieba-win32-ia32-msvc" "1.6.1" + "@node-rs/jieba-win32-x64-msvc" "1.6.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + +"@popperjs/core@^2.11.5", "@popperjs/core@^2.11.6": + version "2.11.6" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" + integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== + +"@react-aria/ssr@^3.2.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.3.0.tgz#25e81daf0c7a270a4a891159d8d984578e4512d8" + integrity sha512-yNqUDuOVZIUGP81R87BJVi/ZUZp/nYOBXbPsRe7oltJOfErQZD+UezMpw4vM2KRz18cURffvmC8tJ6JTeyDtaQ== + dependencies: + "@babel/runtime" "^7.6.2" + +"@restart/hooks@^0.4.6", "@restart/hooks@^0.4.7": + version "0.4.7" + resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.7.tgz#d79ca6472c01ce04389fc73d4a79af1b5e33cd39" + integrity sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A== + dependencies: + dequal "^2.0.2" + +"@restart/ui@^1.3.1": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.4.0.tgz#8333294fefb045f58852d5bb34367c3323e2edb3" + integrity sha512-5dDj5uDzUgK1iijWPRg6AnxjkHM04XhTQDJirM1h/8tIc7KyLtF9YyjcCpNEn259hPMXswpkfXKNgiag0skPFg== + dependencies: + "@babel/runtime" "^7.18.3" + "@popperjs/core" "^2.11.5" + "@react-aria/ssr" "^3.2.0" + "@restart/hooks" "^0.4.7" + "@types/warning" "^3.0.0" + dequal "^2.0.2" + dom-helpers "^5.2.0" + uncontrollable "^7.2.1" + warning "^4.0.3" + +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@slorber/static-site-generator-webpack-plugin@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz#fc1678bddefab014e2145cbe25b3ce4e1cfc36f3" + integrity sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA== + dependencies: + eval "^0.1.8" + p-map "^4.0.0" + webpack-sources "^3.2.2" + +"@svgr/babel-plugin-add-jsx-attribute@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.3.1.tgz#b9a5d84902be75a05ede92e70b338d28ab63fa74" + integrity sha512-jDBKArXYO1u0B1dmd2Nf8Oy6aTF5vLDfLoO9Oon/GLkqZ/NiggYWZA+a2HpUMH4ITwNqS3z43k8LWApB8S583w== + +"@svgr/babel-plugin-remove-jsx-attribute@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.3.1.tgz#4877995452efc997b36777abe1fde9705ef78e8b" + integrity sha512-dQzyJ4prwjcFd929T43Z8vSYiTlTu8eafV40Z2gO7zy/SV5GT+ogxRJRBIKWomPBOiaVXFg3jY4S5hyEN3IBjQ== + +"@svgr/babel-plugin-remove-jsx-empty-expression@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.3.1.tgz#2d67a0e92904c9be149a5b22d3a3797ce4d7b514" + integrity sha512-HBOUc1XwSU67fU26V5Sfb8MQsT0HvUyxru7d0oBJ4rA2s4HW3PhyAPC7fV/mdsSGpAvOdd8Wpvkjsr0fWPUO7A== + +"@svgr/babel-plugin-replace-jsx-attribute-value@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.3.1.tgz#306f5247139c53af70d1778f2719647c747998ee" + integrity sha512-C12e6aN4BXAolRrI601gPn5MDFCRHO7C4TM8Kks+rDtl8eEq+NN1sak0eAzJu363x3TmHXdZn7+Efd2nr9I5dA== + +"@svgr/babel-plugin-svg-dynamic-title@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.3.1.tgz#6ce26d34cbc93eb81737ef528528907c292e7aa2" + integrity sha512-6NU55Mmh3M5u2CfCCt6TX29/pPneutrkJnnDCHbKZnjukZmmgUAZLtZ2g6ZoSPdarowaQmAiBRgAHqHmG0vuqA== + +"@svgr/babel-plugin-svg-em-dimensions@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.3.1.tgz#5ade2a724b290873c30529d1d8cd23523856287a" + integrity sha512-HV1NGHYTTe1vCNKlBgq/gKuCSfaRlKcHIADn7P8w8U3Zvujdw1rmusutghJ1pZJV7pDt3Gt8ws+SVrqHnBO/Qw== + +"@svgr/babel-plugin-transform-react-native-svg@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.3.1.tgz#d654f509d692c3a09dfb475757a44bd9f6ad7ddf" + integrity sha512-2wZhSHvTolFNeKDAN/ZmIeSz2O9JSw72XD+o2bNp2QAaWqa8KGpn5Yk5WHso6xqfSAiRzAE+GXlsrBO4UP9LLw== + +"@svgr/babel-plugin-transform-svg-component@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.3.1.tgz#21a285dbffdce9567c437ebf0d081bf9210807e6" + integrity sha512-cZ8Tr6ZAWNUFfDeCKn/pGi976iWSkS8ijmEYKosP+6ktdZ7lW9HVLHojyusPw3w0j8PI4VBeWAXAmi/2G7owxw== + +"@svgr/babel-preset@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.3.1.tgz#8bd1ead79637d395e9362b01dd37cfd59702e152" + integrity sha512-tQtWtzuMMQ3opH7je+MpwfuRA1Hf3cKdSgTtAYwOBDfmhabP7rcTfBi3E7V3MuwJNy/Y02/7/RutvwS1W4Qv9g== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^6.3.1" + "@svgr/babel-plugin-remove-jsx-attribute" "^6.3.1" + "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.3.1" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.3.1" + "@svgr/babel-plugin-svg-dynamic-title" "^6.3.1" + "@svgr/babel-plugin-svg-em-dimensions" "^6.3.1" + "@svgr/babel-plugin-transform-react-native-svg" "^6.3.1" + "@svgr/babel-plugin-transform-svg-component" "^6.3.1" + +"@svgr/core@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.3.1.tgz#752adf49d8d5473b15d76ca741961de093f715bd" + integrity sha512-Sm3/7OdXbQreemf9aO25keerZSbnKMpGEfmH90EyYpj1e8wMD4TuwJIb3THDSgRMWk1kYJfSRulELBy4gVgZUA== + dependencies: + "@svgr/plugin-jsx" "^6.3.1" + camelcase "^6.2.0" + cosmiconfig "^7.0.1" + +"@svgr/hast-util-to-babel-ast@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.3.1.tgz#59614e24d2a4a28010e02089213b3448d905769d" + integrity sha512-NgyCbiTQIwe3wHe/VWOUjyxmpUmsrBjdoIxKpXt3Nqc3TN30BpJG22OxBvVzsAh9jqep0w0/h8Ywvdk3D9niNQ== + dependencies: + "@babel/types" "^7.18.4" + entities "^4.3.0" + +"@svgr/plugin-jsx@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.3.1.tgz#de7b2de824296b836d6b874d498377896e367f50" + integrity sha512-r9+0mYG3hD4nNtUgsTXWGYJomv/bNd7kC16zvsM70I/bGeoCi/3lhTmYqeN6ChWX317OtQCSZZbH4wq9WwoXbw== + dependencies: + "@babel/core" "^7.18.5" + "@svgr/babel-preset" "^6.3.1" + "@svgr/hast-util-to-babel-ast" "^6.3.1" + svg-parser "^2.0.4" + +"@svgr/plugin-svgo@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.3.1.tgz#3c1ff2efaed10e5c5d35a6cae7bacaedc18b5d4a" + integrity sha512-yJIjTDKPYqzFVjmsbH5EdIwEsmKxjxdXSGJVLeUgwZOZPAkNQmD1v7LDbOdOKbR44FG8465Du+zWPdbYGnbMbw== + dependencies: + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + svgo "^2.8.0" + +"@svgr/webpack@^6.2.0", "@svgr/webpack@^6.2.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.3.1.tgz#001d03236ebb03bf47c0a4b92d5423e05095ebe6" + integrity sha512-eODxwIUShLxSMaRjzJtrj9wg89D75JLczvWg9SaB5W+OtVTkiC1vdGd8+t+pf5fTlBOy4RRXAq7x1E3DUl3D0A== + dependencies: + "@babel/core" "^7.18.5" + "@babel/plugin-transform-react-constant-elements" "^7.17.12" + "@babel/preset-env" "^7.18.2" + "@babel/preset-react" "^7.17.12" + "@babel/preset-typescript" "^7.17.12" + "@svgr/core" "^6.3.1" + "@svgr/plugin-jsx" "^6.3.1" + "@svgr/plugin-svgo" "^6.3.1" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207" + integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.31" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" + integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" + integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + +"@types/history@^4.7.11": + version "4.7.11" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== + +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== + dependencies: + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*": + version "18.7.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154" + integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg== + +"@types/node@^17.0.5": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/parse5@^5.0.0": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" + integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + +"@types/prop-types@*", "@types/prop-types@^15.7.5": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/react-is@^16.7.1 || ^17.0.0": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a" + integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw== + dependencies: + "@types/react" "*" + +"@types/react-router-config@*", "@types/react-router-config@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" + integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router-dom@*": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.19" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.19.tgz#9b404246fba7f91474d7008a3d48c17b6e075ad6" + integrity sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + +"@types/react-transition-group@^4.4.4", "@types/react-transition-group@^4.4.5": + version "4.4.5" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" + integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@>=16.9.11": + version "18.0.20" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.20.tgz#e4c36be3a55eb5b456ecf501bd4a00fd4fd0c9ab" + integrity sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/sax@^1.2.1": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" + integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== + dependencies: + "@types/node" "*" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA== + +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + +address@^1.0.1, address@^1.1.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.1.tgz#25bb61095b7522d65b357baa11bc05492d4c8acd" + integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +algoliasearch-helper@^3.10.0: + version "3.11.1" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.11.1.tgz#d83ab7f1a2a374440686ef7a144b3c288b01188a" + integrity sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw== + dependencies: + "@algolia/events" "^4.0.1" + +algoliasearch@^4.0.0, algoliasearch@^4.12.0, algoliasearch@^4.13.1: + version "4.14.2" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.2.tgz#63f142583bfc3a9bd3cd4a1b098bf6fe58e56f6c" + integrity sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg== + dependencies: + "@algolia/cache-browser-local-storage" "4.14.2" + "@algolia/cache-common" "4.14.2" + "@algolia/cache-in-memory" "4.14.2" + "@algolia/client-account" "4.14.2" + "@algolia/client-analytics" "4.14.2" + "@algolia/client-common" "4.14.2" + "@algolia/client-personalization" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/logger-console" "4.14.2" + "@algolia/requester-browser-xhr" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/requester-node-http" "4.14.2" + "@algolia/transporter" "4.14.2" + +ansi-align@^3.0.0, ansi-align@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.1.tgz#63cd61c72283a71cb30bd881dbb60adada74bc70" + integrity sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg== + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +arg@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +autocomplete.js@^0.37.0: + version "0.37.1" + resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.37.1.tgz#a29a048d827e7d2bf8f7df8b831766e5cc97df01" + integrity sha512-PgSe9fHYhZEsm/9jggbjtVsGXJkPLvd+9mC7gZJ662vVL5CRWEtm/mIrrzCx0MrNxHVwxD5d00UOn6NsmL2LUQ== + dependencies: + immediate "^3.2.3" + +autoprefixer@^10.3.7, autoprefixer@^10.4.7: + version "10.4.11" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.11.tgz#835136aff1d9cd43640151e0d2dba00f8eac7c1c" + integrity sha512-5lHp6DgRodxlBLSkzHOTcufWFflH1ewfy2hvFQyjrblBFlP/0Yh4O/Wrg4ow8WRlN3AAUFFLAQwX8hTptzqVHg== + dependencies: + browserslist "^4.21.3" + caniuse-lite "^1.0.30001399" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +axios@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" + integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== + dependencies: + follow-redirects "^1.14.7" + +babel-loader@^8.2.5: + version "8.2.5" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" + integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^2.0.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-apply-mdx-type-prop@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" + integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" + "@mdx-js/util" "1.6.22" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-extract-import-names@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" + integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +babel-plugin-polyfill-corejs2@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== + dependencies: + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" + +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base16@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" + integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +bcp-47-match@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-1.0.3.tgz#cb8d03071389a10aff2062b862d6575ffd7cd7ef" + integrity sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +body-parser@1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.0.11: + version "1.0.14" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" + integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +boxen@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +boxen@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-6.2.1.tgz#b098a2278b2cd2845deef2dff2efc38d329b434d" + integrity sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw== + dependencies: + ansi-align "^3.0.1" + camelcase "^6.2.0" + chalk "^4.1.2" + cli-boxes "^3.0.0" + string-width "^5.0.1" + type-fest "^2.5.0" + widest-line "^4.0.1" + wrap-ansi "^8.0.1" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.20.3, browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase-css@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001399, caniuse-lite@^1.0.30001400: + version "1.0.30001407" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz#92281a6ee67cb90bfd8a6a1201fcc2dc19b60a15" + integrity sha512-4ydV+t4P7X3zH83fQWNDX/mQEzYomossfpViCOx9zHBSMV+rIe3LFqglHHtVyvNl1FhTNxPxs3jei82iqOW04w== + +ccount@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.12, cheerio@^1.0.0-rc.3, cheerio@^1.0.0-rc.9: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + +chokidar@^3.4.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +classnames@^2.2.6, classnames@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + +clean-css@^5.2.2, clean-css@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.1.tgz#d0610b0b90d125196a2894d35366f734e5d7aa32" + integrity sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + +clsx@^1.1.1, clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +colord@^2.9.1: + version "2.9.3" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== + +colorette@^2.0.10: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +combine-promises@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" + integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + +consola@^2.15.3: + version "2.15.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" + integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== + +console-control-strings@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.5.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +copy-text-to-clipboard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" + integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== + +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== + dependencies: + fast-glob "^3.2.11" + glob-parent "^6.0.1" + globby "^13.1.1" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + +core-js-compat@^3.25.1: + version "3.25.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.2.tgz#7875573586809909c69e03ef310810c1969ee138" + integrity sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ== + dependencies: + browserslist "^4.21.4" + +core-js-pure@^3.25.1: + version "3.25.2" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.2.tgz#44a4fd873bdd4fecf6ca11512bcefedbe87e744a" + integrity sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA== + +core-js@^3.23.3: + version "3.25.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.2.tgz#2d3670c1455432b53fa780300a6fc1bd8304932c" + integrity sha512-YB4IAT1bjEfxTJ1XYy11hJAKskO+qmhuDBM8/guIfMz4JvdsAQAqvyb97zXX7JgSrfPLG5mRGFWJwJD39ruq2A== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + +cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +css-declaration-sorter@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" + integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== + +css-loader@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" + integrity sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.7" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + +css-minimizer-webpack-plugin@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.1.0.tgz#2ab9f7d8148c48f5d498604025e6e62cf9528855" + integrity sha512-Zd+yz4nta4GXi3pMqF6skO8kjzuCUbr62z8SLMGZZtxWxTGTLopOiabPGNDEyjHCRhnhdA1EfHmqLa2Oekjtng== + dependencies: + cssnano "^5.1.8" + jest-worker "^27.5.1" + postcss "^8.4.13" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-selector-parser@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" + integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== + +css-tree@^1.1.2, css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-advanced@^5.3.8: + version "5.3.8" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.8.tgz#027b1d05ef896d908178c483f0ec4190cb50ef9a" + integrity sha512-xUlLLnEB1LjpEik+zgRNlk8Y/koBPPtONZjp7JKbXigeAmCrFvq9H0pXW5jJV45bQWAlmJ0sKy+IMr0XxLYQZg== + dependencies: + autoprefixer "^10.3.7" + cssnano-preset-default "^5.2.12" + postcss-discard-unused "^5.1.0" + postcss-merge-idents "^5.1.1" + postcss-reduce-idents "^5.2.0" + postcss-zindex "^5.1.0" + +cssnano-preset-default@^5.2.12: + version "5.2.12" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz#ebe6596ec7030e62c3eb2b3c09f533c0644a9a97" + integrity sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew== + dependencies: + css-declaration-sorter "^6.3.0" + cssnano-utils "^3.1.0" + postcss-calc "^8.2.3" + postcss-colormin "^5.3.0" + postcss-convert-values "^5.1.2" + postcss-discard-comments "^5.1.2" + postcss-discard-duplicates "^5.1.0" + postcss-discard-empty "^5.1.1" + postcss-discard-overridden "^5.1.0" + postcss-merge-longhand "^5.1.6" + postcss-merge-rules "^5.1.2" + postcss-minify-font-values "^5.1.0" + postcss-minify-gradients "^5.1.1" + postcss-minify-params "^5.1.3" + postcss-minify-selectors "^5.2.1" + postcss-normalize-charset "^5.1.0" + postcss-normalize-display-values "^5.1.0" + postcss-normalize-positions "^5.1.1" + postcss-normalize-repeat-style "^5.1.1" + postcss-normalize-string "^5.1.0" + postcss-normalize-timing-functions "^5.1.0" + postcss-normalize-unicode "^5.1.0" + postcss-normalize-url "^5.1.0" + postcss-normalize-whitespace "^5.1.1" + postcss-ordered-values "^5.1.3" + postcss-reduce-initial "^5.1.0" + postcss-reduce-transforms "^5.1.0" + postcss-svgo "^5.1.0" + postcss-unique-selectors "^5.1.1" + +cssnano-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" + integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== + +cssnano@^5.1.12, cssnano@^5.1.8: + version "5.1.13" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.13.tgz#83d0926e72955332dc4802a7070296e6258efc0a" + integrity sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ== + dependencies: + cssnano-preset-default "^5.2.12" + lilconfig "^2.0.3" + yaml "^1.10.2" + +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + +csstype@^3.0.2, csstype@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + +debug@2.6.9, debug@^2.6.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +del@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +dequal@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detab@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" + integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== + dependencies: + repeat-string "^1.5.4" + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +detect-port-alt@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" + integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +detect-port@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" + integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +direction@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/direction/-/direction-1.0.4.tgz#2b86fb686967e987088caf8b89059370d4837442" + integrity sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ== + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^5.2.2: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +docusaurus-lunr-search@^2.1.15: + version "2.2.0" + resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-2.2.0.tgz#b8281a49577f97b769fa4ec654057f82db5b3132" + integrity sha512-8fvxZKLYWseyjq6JoZGwovdMr/32hxL0OgDebZEWEPzXtD0uuR+gDNKPyNmT1WFJ7Wn33vQ2p1Ecnj0vS1uAAw== + dependencies: + autocomplete.js "^0.37.0" + classnames "^2.2.6" + gauge "^3.0.0" + hast-util-select "^4.0.0" + hast-util-to-text "^2.0.0" + hogan.js "^3.0.2" + lunr "^2.3.8" + lunr-languages "^1.4.0" + minimatch "^3.0.4" + object-assign "^4.1.1" + rehype-parse "^7.0.1" + to-vfile "^6.1.0" + unified "^9.0.0" + unist-util-is "^4.0.2" + +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@4.3.1, domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.2.2, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== + +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.251: + version "1.4.255" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz#dc52d1095b876ed8acf25865db10265b02b1d6e1" + integrity sha512-H+mFNKow6gi2P5Gi2d1Fvd3TUEJlB9CF7zYaIV9T83BE3wP1xZ0mRPbNTm0KUjyd1QiVy7iKXuIcjlDtBQMiAQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +emoticon@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-3.2.0.tgz#c008ca7d7620fac742fe1bf4af8ff8fed154ae7f" + integrity sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" + integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" + integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== + +entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eta@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" + integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eval@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.8.tgz#2b903473b8cc1d1989b83a1e7923f883eb357f85" + integrity sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw== + dependencies: + "@types/node" "*" + require-like ">= 0.1.1" + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +express@^4.17.3: + version "4.18.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" + integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.0" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.10.3" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.11, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fbemitter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" + integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== + dependencies: + fbjs "^3.0.0" + +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^3.0.0, fbjs@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.30" + +feed@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" + integrity sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ== + dependencies: + xml-js "^1.6.11" + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +filesize@^8.0.6: + version "8.0.7" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" + integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flux@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" + integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== + dependencies: + fbemitter "^3.0.0" + fbjs "^3.0.1" + +follow-redirects@^1.0.0, follow-redirects@^1.14.7: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +fork-ts-checker-webpack-plugin@^6.5.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" + integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +github-slugger@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" + integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" + integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + dependencies: + ini "2.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +globby@^13.1.1: + version "13.1.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" + integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +gray-matter@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" + integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== + dependencies: + js-yaml "^3.13.1" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hast-to-hyperscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" + integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + dependencies: + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.3.0" + unist-util-is "^4.0.0" + web-namespaces "^1.0.0" + +hast-util-from-parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" + integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + dependencies: + "@types/parse5" "^5.0.0" + hastscript "^6.0.0" + property-information "^5.0.0" + vfile "^4.0.0" + vfile-location "^3.2.0" + web-namespaces "^1.0.0" + +hast-util-has-property@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz#9f137565fad6082524b382c1e7d7d33ca5059f36" + integrity sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg== + +hast-util-is-element@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" + integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ== + +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hast-util-raw@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.1.tgz#973b15930b7529a7b66984c98148b46526885977" + integrity sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig== + dependencies: + "@types/hast" "^2.0.0" + hast-util-from-parse5 "^6.0.0" + hast-util-to-parse5 "^6.0.0" + html-void-elements "^1.0.0" + parse5 "^6.0.0" + unist-util-position "^3.0.0" + vfile "^4.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-select@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-4.0.2.tgz#ae3ef2860e02cda2ad3a2e72b47c1f5e8f44e9e7" + integrity sha512-8EEG2//bN5rrzboPWD2HdS3ugLijNioS1pqOTIolXNf67xxShYw4SQEmVXd3imiBG+U2bC2nVTySr/iRAA7Cjg== + dependencies: + bcp-47-match "^1.0.0" + comma-separated-tokens "^1.0.0" + css-selector-parser "^1.0.0" + direction "^1.0.0" + hast-util-has-property "^1.0.0" + hast-util-is-element "^1.0.0" + hast-util-to-string "^1.0.0" + hast-util-whitespace "^1.0.0" + not "^0.1.0" + nth-check "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + unist-util-visit "^2.0.0" + zwitch "^1.0.0" + +hast-util-to-parse5@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" + integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== + dependencies: + hast-to-hyperscript "^9.0.0" + property-information "^5.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-to-string@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" + integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== + +hast-util-to-text@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b" + integrity sha512-8nsgCARfs6VkwH2jJU9b8LNTuR4700na+0h3PqCaEk4MAnMDeu5P0tP8mjk9LLNGxIeQRLbiDbZVw6rku+pYsQ== + dependencies: + hast-util-is-element "^1.0.0" + repeat-string "^1.0.0" + unist-util-find-after "^3.0.0" + +hast-util-whitespace@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" + integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +history@^4.9.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + +hogan.js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" + integrity sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg== + dependencies: + mkdirp "0.3.0" + nopt "1.0.10" + +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +htm@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/htm/-/htm-3.1.1.tgz#49266582be0dc66ed2235d5ea892307cc0c24b78" + integrity sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ== + +html-dom-parser@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-1.2.0.tgz#8f689b835982ffbf245eda99730e92b8462c111e" + integrity sha512-2HIpFMvvffsXHFUFjso0M9LqM+1Lm22BF+Df2ba+7QHJXjk63pWChEnI6YG27eaWqUdfnh5/Vy+OXrNTtepRsg== + dependencies: + domhandler "4.3.1" + htmlparser2 "7.2.0" + +html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + +html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-react-parser@^1.4.5: + version "1.4.14" + resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-1.4.14.tgz#577b7a90be0c61eebbbc488d914ad08398c79ef5" + integrity sha512-pxhNWGie8Y+DGDpSh8cTa0k3g8PsDcwlfolA+XxYo1AGDeB6e2rdlyv4ptU9bOTiZ2i3fID+6kyqs86MN0FYZQ== + dependencies: + domhandler "4.3.1" + html-dom-parser "1.2.0" + react-property "2.0.0" + style-to-js "1.1.1" + +html-tags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== + +html-void-elements@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" + integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== + +html-webpack-plugin@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" + integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5" + integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.2" + domutils "^2.8.0" + entities "^3.0.1" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +htmlparser2@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" + integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + domutils "^3.0.1" + entities "^4.3.0" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +image-size@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" + integrity sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg== + dependencies: + queue "6.0.2" + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immer@^9.0.7: + version "9.0.15" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" + integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== + +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +infima@0.2.0-alpha.42: + version "0.2.0-alpha.42" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.42.tgz#f6e86a655ad40877c6b4d11b2ede681eb5470aa5" + integrity sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +ini@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + +ini@^1.3.5, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-alphabetical@1.0.4, is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.9.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + dependencies: + has "^1.0.3" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-installed-globally@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" + integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== + +is-root@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" + integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5, jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +joi@^17.6.0: + version "17.6.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" + integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^2.1.2, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +klona@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +latest-version@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lilconfig@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" + integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loader-utils@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" + integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.curry@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" + integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.flow@^3.3.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" + integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniq@4.5.0, lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lunr-languages@^1.4.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.9.0.tgz#7105230807788a112a69910561b7bbd055a0e588" + integrity sha512-Be5vFuc8NAheOIjviCRms3ZqFFBlzns3u9DXpPSZvALetgnydAN0poV71pVLFn0keYy/s4VblMMkqewTLe+KPg== + +lunr@^2.3.8, lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +mark.js@^8.11.1: + version "8.11.1" + resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" + integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== + +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +mdast-squeeze-paragraphs@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" + integrity sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ== + dependencies: + unist-util-remove "^2.0.0" + +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" + integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== + dependencies: + unist-util-visit "^2.0.0" + +mdast-util-to-hast@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" + integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memfs@^3.1.2, memfs@^3.4.3: + version "3.4.7" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" + integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== + dependencies: + fs-monkey "^1.0.3" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mini-create-react-context@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" + integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== + dependencies: + "@babel/runtime" "^7.12.1" + tiny-warning "^1.0.3" + +mini-css-extract-plugin@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" + integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== + dependencies: + schema-utils "^4.0.0" + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== + +mrmime@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +nopt@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +not@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/not/-/not-0.1.0.tgz#c9691c1746c55dcfbe54cbd8bd4ff041bc2b519d" + integrity sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== + +nth-check@^2.0.0, nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.9, open@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-numeric-range@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" + integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== + +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + +parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parse5@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.1.tgz#4649f940ccfb95d8754f37f73078ea20afe0c746" + integrity sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg== + dependencies: + entities "^4.4.0" + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== + +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +postcss-calc@^8.2.3: + version "8.2.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" + integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== + dependencies: + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" + +postcss-colormin@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" + integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + colord "^2.9.1" + postcss-value-parser "^4.2.0" + +postcss-convert-values@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz#31586df4e184c2e8890e8b34a0b9355313f503ab" + integrity sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g== + dependencies: + browserslist "^4.20.3" + postcss-value-parser "^4.2.0" + +postcss-discard-comments@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" + integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== + +postcss-discard-duplicates@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" + integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== + +postcss-discard-empty@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" + integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== + +postcss-discard-overridden@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" + integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== + +postcss-discard-unused@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" + integrity sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw== + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-loader@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" + integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== + dependencies: + cosmiconfig "^7.0.0" + klona "^2.0.5" + semver "^7.3.7" + +postcss-merge-idents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz#7753817c2e0b75d0853b56f78a89771e15ca04a1" + integrity sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw== + dependencies: + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-merge-longhand@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz#f378a8a7e55766b7b644f48e5d8c789ed7ed51ce" + integrity sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw== + dependencies: + postcss-value-parser "^4.2.0" + stylehacks "^5.1.0" + +postcss-merge-rules@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz#7049a14d4211045412116d79b751def4484473a5" + integrity sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + cssnano-utils "^3.1.0" + postcss-selector-parser "^6.0.5" + +postcss-minify-font-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" + integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-minify-gradients@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" + integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== + dependencies: + colord "^2.9.1" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-minify-params@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz#ac41a6465be2db735099bbd1798d85079a6dc1f9" + integrity sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg== + dependencies: + browserslist "^4.16.6" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-minify-selectors@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" + integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-normalize-charset@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" + integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== + +postcss-normalize-display-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" + integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-positions@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" + integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-repeat-style@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" + integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-string@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" + integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-timing-functions@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" + integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-normalize-unicode@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz#3d23aede35e160089a285e27bf715de11dc9db75" + integrity sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ== + dependencies: + browserslist "^4.16.6" + postcss-value-parser "^4.2.0" + +postcss-normalize-url@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" + integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== + dependencies: + normalize-url "^6.0.1" + postcss-value-parser "^4.2.0" + +postcss-normalize-whitespace@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" + integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-ordered-values@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" + integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== + dependencies: + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" + +postcss-reduce-idents@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" + integrity sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-reduce-initial@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz#fc31659ea6e85c492fb2a7b545370c215822c5d6" + integrity sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw== + dependencies: + browserslist "^4.16.6" + caniuse-api "^3.0.0" + +postcss-reduce-transforms@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" + integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-sort-media-queries@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz#f48a77d6ce379e86676fc3f140cf1b10a06f6051" + integrity sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg== + dependencies: + sort-css-media-queries "2.1.0" + +postcss-svgo@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" + integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== + dependencies: + postcss-value-parser "^4.2.0" + svgo "^2.7.0" + +postcss-unique-selectors@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" + integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== + dependencies: + postcss-selector-parser "^6.0.5" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss-zindex@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" + integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== + +postcss@^8.3.11, postcss@^8.4.13, postcss@^8.4.14, postcss@^8.4.7: + version "8.4.16" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c" + integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +preact@^10.0.0: + version "10.11.0" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.0.tgz#26af45a0613f4e17a197cc39d7a1ea23e09b2532" + integrity sha512-Fk6+vB2kb6mSJfDgODq0YDhMfl0HNtK5+Uc9QqECO4nlyPAQwCI+BKyWO//idA7ikV7o+0Fm6LQmNuQi1wXI1w== + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + +pretty-time@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" + integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== + +prism-react-renderer@^1.2.1, prism-react-renderer@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" + integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== + +prismjs@^1.28.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + +prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types-extra@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" + integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== + dependencies: + react-is "^16.3.2" + warning "^4.0.0" + +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +property-information@^5.0.0, property-information@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +pupa@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + +pure-color@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" + integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== + +qs@6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +queue@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@1.2.8, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-base16-styling@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" + integrity sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ== + dependencies: + base16 "^1.0.0" + lodash.curry "^4.0.1" + lodash.flow "^3.3.0" + pure-color "^1.2.0" + +react-bootstrap@^2.1.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.5.0.tgz#e25e649e37f080d38eeb92ad5b4ed562a1d7de62" + integrity sha512-j/aLR+okzbYk61TM3eDOU1NqOqnUdwyVrF+ojoCRUxPdzc2R0xXvqyRsjSoyRoCo7n82Fs/LWjPCin/QJNdwvA== + dependencies: + "@babel/runtime" "^7.17.2" + "@restart/hooks" "^0.4.6" + "@restart/ui" "^1.3.1" + "@types/react-transition-group" "^4.4.4" + classnames "^2.3.1" + dom-helpers "^5.2.1" + invariant "^2.2.4" + prop-types "^15.8.1" + prop-types-extra "^1.1.0" + react-transition-group "^4.4.2" + uncontrollable "^7.2.1" + warning "^4.0.3" + +react-dev-utils@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" + integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ== + dependencies: + "@babel/code-frame" "^7.16.0" + address "^1.1.2" + browserslist "^4.18.1" + chalk "^4.1.2" + cross-spawn "^7.0.3" + detect-port-alt "^1.1.6" + escape-string-regexp "^4.0.0" + filesize "^8.0.6" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.5.0" + global-modules "^2.0.0" + globby "^11.0.4" + gzip-size "^6.0.0" + immer "^9.0.7" + is-root "^2.1.0" + loader-utils "^3.2.0" + open "^8.4.0" + pkg-up "^3.1.0" + prompts "^2.4.2" + react-error-overlay "^6.0.11" + recursive-readdir "^2.2.2" + shell-quote "^1.7.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +react-dom@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +react-error-overlay@^6.0.11: + version "6.0.11" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" + integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== + +react-fast-compare@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" + integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== + +react-helmet-async@*, react-helmet-async@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" + integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== + dependencies: + "@babel/runtime" "^7.12.5" + invariant "^2.2.4" + prop-types "^15.7.2" + react-fast-compare "^3.2.0" + shallowequal "^1.1.0" + +react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-json-view@^1.21.3: + version "1.21.3" + resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" + integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== + dependencies: + flux "^4.0.1" + react-base16-styling "^0.6.0" + react-lifecycles-compat "^3.0.4" + react-textarea-autosize "^8.3.2" + +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-loadable-ssr-addon-v5-slorber@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" + integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== + dependencies: + "@babel/runtime" "^7.10.3" + +react-property@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.0.tgz#2156ba9d85fa4741faf1918b38efc1eae3c6a136" + integrity sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw== + +react-router-config@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" + integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== + dependencies: + "@babel/runtime" "^7.1.2" + +react-router-dom@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.3.tgz#8779fc28e6691d07afcaf98406d3812fe6f11199" + integrity sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng== + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.3.3" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.3.3, react-router@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288" + integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w== + dependencies: + "@babel/runtime" "^7.12.13" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.4.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-scroll@^1.8.7: + version "1.8.7" + resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.7.tgz#8020035329efad00f03964e18aff6822137de3aa" + integrity sha512-fBOIwweAlhicx8RqP9tQXn/Uhd+DTtVRjw+0VBsIn1Z+MjRYLhTZ0tMoTAU1vOD3dce8mI6copexI4yWII+Luw== + dependencies: + lodash.throttle "^4.1.1" + prop-types "^15.7.2" + +react-textarea-autosize@^8.3.2: + version "8.3.4" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz#270a343de7ad350534141b02c9cb78903e553524" + integrity sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ== + dependencies: + "@babel/runtime" "^7.10.2" + use-composed-ref "^1.3.0" + use-latest "^1.2.1" + +react-transition-group@^4.4.2, react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + +react@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +reading-time@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" + integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + +regenerate-unicode-properties@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regenerator-transform@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" + integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139" + integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +registry-auth-token@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== + dependencies: + rc "1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +rehype-parse@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" + integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw== + dependencies: + hast-util-from-parse5 "^6.0.0" + parse5 "^6.0.0" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +remark-emoji@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" + integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== + dependencies: + emoticon "^3.2.0" + node-emoji "^1.10.0" + unist-util-visit "^2.0.3" + +remark-footnotes@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" + integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== + +remark-mdx@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" + integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== + dependencies: + "@babel/core" "7.12.9" + "@babel/helper-plugin-utils" "7.10.4" + "@babel/plugin-proposal-object-rest-spread" "7.12.1" + "@babel/plugin-syntax-jsx" "7.12.1" + "@mdx-js/util" "1.6.22" + is-alphabetical "1.0.4" + remark-parse "8.0.3" + unified "9.2.0" + +remark-parse@8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" + integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== + dependencies: + ccount "^1.0.0" + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^2.0.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^2.0.0" + vfile-location "^3.0.0" + xtend "^4.0.1" + +remark-squeeze-paragraphs@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" + integrity sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw== + dependencies: + mdast-squeeze-paragraphs "^4.0.0" + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +repeat-string@^1.0.0, repeat-string@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +"require-like@>= 0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" + integrity sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + +resolve@^1.1.6, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.3.2: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rtl-detect@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" + integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== + +rtlcss@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" + integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== + dependencies: + find-up "^5.0.0" + picocolors "^1.0.0" + postcss "^8.3.11" + strip-json-comments "^3.1.1" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.5.4: + version "7.5.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" + integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw== + dependencies: + tslib "^2.1.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + dependencies: + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + +semver@^5.4.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-handler@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" + integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +sitemap@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" + integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== + dependencies: + "@types/node" "^17.0.5" + "@types/sax" "^1.2.1" + arg "^5.0.0" + sax "^1.2.4" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +sort-css-media-queries@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" + integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +std-env@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.2.1.tgz#00e260ec3901333537125f81282b9296b00d7304" + integrity sha512-D/uYFWkI/31OrnKmXZqGAGK5GbQRPp/BWA1nuITcc6ICblhhuQUPHS5E2GSCVS7Hwhf4ciq8qsATwBUxv+lI6w== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +style-to-js@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.1.tgz#417786986cda61d4525c80aed9d1123a6a7af9b8" + integrity sha512-RJ18Z9t2B02sYhZtfWKQq5uplVctgvjTfLWT7+Eb1zjUjIrWzX5SdlkwLGQozrqarTmEzJJ/YmdNJCUNI47elg== + dependencies: + style-to-object "0.3.0" + +style-to-object@0.3.0, style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + +stylehacks@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520" + integrity sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q== + dependencies: + browserslist "^4.16.6" + postcss-selector-parser "^6.0.4" + +stylis@4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" + integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svg-parser@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + +svgo@^2.7.0, svgo@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" + integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^4.1.3" + css-tree "^1.1.3" + csso "^4.2.0" + picocolors "^1.0.0" + stable "^0.1.8" + +tapable@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + terser "^5.14.1" + +terser@^5.10.0, terser@^5.14.1: + version "5.15.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" + integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +tiny-invariant@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" + integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + +tiny-warning@^1.0.0, tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-vfile@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-6.1.0.tgz#5f7a3f65813c2c4e34ee1f7643a5646344627699" + integrity sha512-BxX8EkCxOAZe+D/ToHdDsJcVI4HqQfmw0tCkp31zf3dNP/XWIAjU4CmeuSwsSoOzOTqHPOL0KUzyZqJplkD0Qw== + dependencies: + is-buffer "^2.0.0" + vfile "^4.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ== + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^2.5.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +ua-parser-js@^0.7.30: + version "0.7.31" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" + integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + +uncontrollable@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738" + integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ== + dependencies: + "@babel/runtime" "^7.6.3" + "@types/react" ">=16.9.11" + invariant "^2.2.4" + react-lifecycles-compat "^3.0.4" + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +unified@9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" + integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unified@^9.0.0, unified@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +unist-builder@2.0.3, unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" + integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== + +unist-util-find-after@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz#5c65fcebf64d4f8f496db46fa8fd0fbf354b43e6" + integrity sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ== + dependencies: + unist-util-is "^4.0.0" + +unist-util-generated@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" + integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== + +unist-util-is@^4.0.0, unist-util-is@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-position@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" + integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== + +unist-util-remove-position@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" + integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== + dependencies: + unist-util-visit "^2.0.0" + +unist-util-remove@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" + integrity sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q== + dependencies: + unist-util-is "^4.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" + integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +update-notifier@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" + integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== + dependencies: + boxen "^5.0.0" + chalk "^4.1.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-loader@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + +use-composed-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" + integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== + +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + +use-latest@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" + integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== + dependencies: + use-isomorphic-layout-effect "^1.1.1" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== + +utility-types@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" + integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vfile-location@^3.0.0, vfile-location@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" + integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +wait-on@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" + integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== + dependencies: + axios "^0.25.0" + joi "^17.6.0" + lodash "^4.17.21" + minimist "^1.2.5" + rxjs "^7.5.4" + +warning@^4.0.0, warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +web-namespaces@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" + integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-bundle-analyzer@^4.5.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.1.tgz#bee2ee05f4ba4ed430e4831a319126bb4ed9f5a6" + integrity sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.9.3: + version "4.11.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" + integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + +webpack-merge@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.2, webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.73.0: + version "5.74.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" + integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + +webpackbar@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" + integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== + dependencies: + chalk "^4.1.0" + consola "^2.15.3" + pretty-time "^1.1.0" + std-env "^3.0.1" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +widest-line@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" + integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== + dependencies: + string-width "^5.0.1" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" + integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.3.1: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +ws@^8.4.2: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +xml-js@^1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" + integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== + dependencies: + sax "^1.2.4" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== From f48c3748942dc15ae1af2aa146745237b607cfca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 20 Sep 2022 23:27:28 +0200 Subject: [PATCH 002/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado From 62d16e9c4a2d2951978908ceee38ba705897c8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 20 Sep 2022 23:34:35 +0200 Subject: [PATCH 003/115] fix: add static/CNAME file (#17) Co-authored-by: ecunado --- static/CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 static/CNAME diff --git a/static/CNAME b/static/CNAME new file mode 100644 index 0000000..61792ed --- /dev/null +++ b/static/CNAME @@ -0,0 +1 @@ +developer.handpoint.com \ No newline at end of file From 5673459ce5c2ed733fee5ca6a951ec4337878120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 20 Sep 2022 23:35:18 +0200 Subject: [PATCH 004/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado From 719a19a24ed8d662d259faa26192304771225692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 20 Sep 2022 23:40:17 +0200 Subject: [PATCH 005/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado --- docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index dee3694..35f5c30 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -7,7 +7,7 @@ module.exports = { tagline: 'Global Payments-Powered Growth for SaaS', url: 'https://developer.handpoint.com', baseUrl: '/', - onBrokenLinks: 'throw', + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', favicon: '/img/favicon.png', organizationName: 'handpoint', // Usually your GitHub org/user name. From fcc38cf9d8f40960133a0bb8e427b6d577233ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 01:40:31 +0200 Subject: [PATCH 006/115] Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado --- setenv.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) mode change 100755 => 100644 setenv.sh diff --git a/setenv.sh b/setenv.sh old mode 100755 new mode 100644 index 9bd1b3f..35648df --- a/setenv.sh +++ b/setenv.sh @@ -2,15 +2,15 @@ if [[ $1 == 'prod' ]] then sed -i 's/handpoint.io/handpoint.com/g' docusaurus.config.js - sed -i "s/url: 'https://developer.handpoint.io'/url: 'https://developer.handpoint.io'/g" docusaurus.config.js + sed -i "s/developer.handpoint.io/developer.handpoint.com/g" docusaurus.config.js sed -i 's/includeCurrentVersion: true/includeCurrentVersion: false/g' docusaurus.config.js - sed -i "s/organizationName: 'handpoint'/organizationName: 'handpoint'/g" docusaurus.config.js - sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js + sed -i "s/organizationName: 'handpointdev'/organizationName: 'handpoint'/g" docusaurus.config.js + sed -i "s/projectName: 'handpointdev.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js sed -i 's/handpoint.io/handpoint.com/g' src/pages/index.js sed -i 's/developer.handpoint.com/developer.handpoint.com/g' static/CNAME else sed -i 's/handpoint.com/handpoint.io/g' docusaurus.config.js - sed -i "s/url: 'https://developer.handpoint.com'/url: 'https://developer.handpoint.io'/g" docusaurus.config.js + sed -i "s/developer.handpoint.com/developer.handpoint.io/g" docusaurus.config.js sed -i 's/includeCurrentVersion: false/includeCurrentVersion: true/g' docusaurus.config.js sed -i "s/organizationName: 'handpoint'/organizationName: 'handpointdev'/g" docusaurus.config.js sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js From b96dbbef9533b1c8a3c5c1fe06ed5f4c0dd1a907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 01:46:15 +0200 Subject: [PATCH 007/115] Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado From b5ddd337fdddee8714f2e09f66af180389c984a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 01:52:11 +0200 Subject: [PATCH 008/115] Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado --- .github/workflows/deploy.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7f16916..9dc5adf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,6 +45,7 @@ jobs: run: | git config --global user.email "actions@github.com" git config --global user.name "gh-actions" + chmod +x ./setenv.sh if [ "${{ github.ref }}" = "refs/heads/main" ]; then echo "Deploying to production" ./setenv.sh prod @@ -54,4 +55,4 @@ jobs: fi cat docusaurus.config.js yarn install --frozen-lockfile - yarn deploy \ No newline at end of file + yarn deploy From 2e4a42b8a46831b1906566af8f8df6ad6a56bed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 11:32:59 +0200 Subject: [PATCH 009/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado --- .github/workflows/deploy.yml | 2 +- docusaurus.config.js | 16 ++++++++-------- setenv.sh | 18 ++++++++++++++++++ src/pages/cpdocs.js | 2 +- src/pages/index.js | 2 +- static/CNAME | 2 +- static/img/logo.svg | 19 ++++++++++++++++++- 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9dc5adf..7d6a56c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,4 +55,4 @@ jobs: fi cat docusaurus.config.js yarn install --frozen-lockfile - yarn deploy + yarn deploy \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 35f5c30..ad61b49 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -7,8 +7,8 @@ module.exports = { tagline: 'Global Payments-Powered Growth for SaaS', url: 'https://developer.handpoint.com', baseUrl: '/', - onBrokenLinks: 'warn', - onBrokenMarkdownLinks: 'warn', + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'throw', favicon: '/img/favicon.png', organizationName: 'handpoint', // Usually your GitHub org/user name. projectName: 'handpoint.github.io', // Usually your repo name. @@ -210,7 +210,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'ios', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: 'ios', routeBasePath: 'ios', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -224,7 +224,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -237,7 +237,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'restapi', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: 'restapi', routeBasePath: 'restapi', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -250,7 +250,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -262,7 +262,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'express', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: 'express', routeBasePath: 'express', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -274,7 +274,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'android', - includeCurrentVersion: false, + includeCurrentVersion: false, // dev: Change to true path: './android', routeBasePath: 'android', sidebarPath: require.resolve('./sidebarsAndroid.js'), diff --git a/setenv.sh b/setenv.sh index 35648df..9aa8dcd 100644 --- a/setenv.sh +++ b/setenv.sh @@ -1,6 +1,23 @@ #!/bin/bash if [[ $1 == 'prod' ]] then +<<<<<<< HEAD + sed -i '' 's/handpoint.io/handpoint.com/g' docusaurus.config.js + sed -i '' "s/developer.handpoint.io/developer.handpoint.com/g" docusaurus.config.js + sed -i '' 's/includeCurrentVersion: true, \/\/ dev/includeCurrentVersion: false, \/\/ dev/g' docusaurus.config.js + sed -i '' "s/organizationName: 'handpointdev'/organizationName: 'handpoint'/g" docusaurus.config.js + sed -i '' "s/projectName: 'handpointdev.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js + sed -i '' 's/handpoint.io/handpoint.com/g' src/pages/index.js + sed -i '' 's/developer.handpoint.com/developer.handpoint.com/g' static/CNAME +else + sed -i '' 's/handpoint.com/handpoint.io/g' docusaurus.config.js + sed -i '' "s/developer.handpoint.com/developer.handpoint.io/g" docusaurus.config.js + sed -i '' 's/includeCurrentVersion: false, \/\/ dev/includeCurrentVersion: true, \/\/ dev/g' docusaurus.config.js + sed -i '' "s/organizationName: 'handpoint'/organizationName: 'handpointdev'/g" docusaurus.config.js + sed -i '' "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js + sed -i '' 's/handpoint.com/handpoint.io/g' src/pages/index.js + sed -i '' 's/developer.handpoint.com/developer.handpoint.io/g' static/CNAME +======= sed -i 's/handpoint.io/handpoint.com/g' docusaurus.config.js sed -i "s/developer.handpoint.io/developer.handpoint.com/g" docusaurus.config.js sed -i 's/includeCurrentVersion: true/includeCurrentVersion: false/g' docusaurus.config.js @@ -16,4 +33,5 @@ else sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js sed -i 's/handpoint.com/handpoint.io/g' src/pages/index.js sed -i 's/developer.handpoint.com/handpointdev.github.io/g' static/CNAME +>>>>>>> dev fi \ No newline at end of file diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 62e4d44..9e4b3a2 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -115,7 +115,7 @@ function Header() { padding: '80px', width: '100%' }}> - Logo + Logo

- Logo + Logo

Artboard 2 \ No newline at end of file + + + + + + + + + + + + + + + + + + From 5fb3a4ed5eb55dd853bc0e2219153b26c115c880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 11:36:06 +0200 Subject: [PATCH 010/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado --- setenv.sh | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/setenv.sh b/setenv.sh index 9aa8dcd..6e97e87 100644 --- a/setenv.sh +++ b/setenv.sh @@ -1,26 +1,9 @@ #!/bin/bash if [[ $1 == 'prod' ]] then -<<<<<<< HEAD - sed -i '' 's/handpoint.io/handpoint.com/g' docusaurus.config.js - sed -i '' "s/developer.handpoint.io/developer.handpoint.com/g" docusaurus.config.js - sed -i '' 's/includeCurrentVersion: true, \/\/ dev/includeCurrentVersion: false, \/\/ dev/g' docusaurus.config.js - sed -i '' "s/organizationName: 'handpointdev'/organizationName: 'handpoint'/g" docusaurus.config.js - sed -i '' "s/projectName: 'handpointdev.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js - sed -i '' 's/handpoint.io/handpoint.com/g' src/pages/index.js - sed -i '' 's/developer.handpoint.com/developer.handpoint.com/g' static/CNAME -else - sed -i '' 's/handpoint.com/handpoint.io/g' docusaurus.config.js - sed -i '' "s/developer.handpoint.com/developer.handpoint.io/g" docusaurus.config.js - sed -i '' 's/includeCurrentVersion: false, \/\/ dev/includeCurrentVersion: true, \/\/ dev/g' docusaurus.config.js - sed -i '' "s/organizationName: 'handpoint'/organizationName: 'handpointdev'/g" docusaurus.config.js - sed -i '' "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js - sed -i '' 's/handpoint.com/handpoint.io/g' src/pages/index.js - sed -i '' 's/developer.handpoint.com/developer.handpoint.io/g' static/CNAME -======= sed -i 's/handpoint.io/handpoint.com/g' docusaurus.config.js sed -i "s/developer.handpoint.io/developer.handpoint.com/g" docusaurus.config.js - sed -i 's/includeCurrentVersion: true/includeCurrentVersion: false/g' docusaurus.config.js + sed -i 's/includeCurrentVersion: true, \/\/ dev/includeCurrentVersion: false, \/\/ dev/g' docusaurus.config.js sed -i "s/organizationName: 'handpointdev'/organizationName: 'handpoint'/g" docusaurus.config.js sed -i "s/projectName: 'handpointdev.github.io'/projectName: 'handpoint.github.io'/g" docusaurus.config.js sed -i 's/handpoint.io/handpoint.com/g' src/pages/index.js @@ -28,10 +11,9 @@ else else sed -i 's/handpoint.com/handpoint.io/g' docusaurus.config.js sed -i "s/developer.handpoint.com/developer.handpoint.io/g" docusaurus.config.js - sed -i 's/includeCurrentVersion: false/includeCurrentVersion: true/g' docusaurus.config.js + sed -i 's/includeCurrentVersion: false, \/\/ dev/includeCurrentVersion: true, \/\/ dev/g' docusaurus.config.js sed -i "s/organizationName: 'handpoint'/organizationName: 'handpointdev'/g" docusaurus.config.js sed -i "s/projectName: 'handpoint.github.io'/projectName: 'handpointdev.github.io'/g" docusaurus.config.js sed -i 's/handpoint.com/handpoint.io/g' src/pages/index.js - sed -i 's/developer.handpoint.com/handpointdev.github.io/g' static/CNAME ->>>>>>> dev + sed -i 's/developer.handpoint.com/developer.handpoint.io/g' static/CNAME fi \ No newline at end of file From 2ec0fb4da2271bf710678934c99ffaba36277f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 11:52:42 +0200 Subject: [PATCH 011/115] chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado --- README.md | 2 +- javascript/javascriptmethods.md | 550 ++++++++++++++++++++++++++++++++ 2 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 javascript/javascriptmethods.md diff --git a/README.md b/README.md index 2ea1165..7440cdb 100644 --- a/README.md +++ b/README.md @@ -79,4 +79,4 @@ Every time we want to integrate changes from a feature branch to the `dev` branc If you are writing documentation for a new version, you have to follow the steps in the section [Generate a new SDK version](#generate-a-new-sdk-version) before merging to `main` branch. -Once the changes are tested in the staging environment, another PR has to be created to merge the changes from `dev` branch to `main` branch. This PR will be reviewed by two team members and merged to `main` branch. This will trigger a deployment to the production environment (It can take up to 5 minutes to be deployed). \ No newline at end of file +Once the changes are tested in the staging environment, another PR has to be created to merge the changes from `dev` branch to `main` branch. This PR will be reviewed by two team members and merged to `main` branch. This will trigger a deployment to the production environment (It can take up to 5 minutes to be deployed). diff --git a/javascript/javascriptmethods.md b/javascript/javascriptmethods.md new file mode 100644 index 0000000..0375310 --- /dev/null +++ b/javascript/javascriptmethods.md @@ -0,0 +1,550 @@ +--- +sidebar_position: 9 +id: javascriptmethods +--- + +# Methods + +## Initialize{#1} + +`Initialize` + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The Actor API key.| +| `dev_or_prod_environment` Required
*boolean* | Value that defines if the actor is targeting a development (true -> cloud.handpoint.io) or production (false -> cloud.handpoint.com) environment.| +| `recovery_EoT_callback` Required
*promise* |Promise that collects the pending transaction results that couldn't be delivered to the POS during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the reader. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may just return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of Device objects| + + +## Connect{#2} + +`Connect` + +Connect the JavaScript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the init call.| + +**Code example** + +```javascript +Handpoint.connect('1234263-TYPE1'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|- **200** code for OK
- **403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` + +Connect the JavaScript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the init call.| + +**Code example** + +```javascript +Handpoint.connect('1234263-TYPE1'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|- `Disconnected` message for OK
- `ERROR disconnecting` message for NOK| + + +## Sale{#4} + +`Sale` + +A sale initiates a payment operation to the card reader. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var [*SaleOptions*](#23) = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.sale('1000', 'USD', [*SaleOptions*](#23) , function (stat) { + console.log('Transaction Status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|A Financial Response object| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` + +A sale which both authorizes the transaction and returns a token representing the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var [*SaleOptions*](#23) = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleAndTokenization('1000', 'USD', [*SaleOptions*](#23) , CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale and Tokenization Response**|A Financial Response object| + + +## Transaction Recovery{#6} + +`StartRecovery` + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the device| +| **Promise Error Response**|The event was not sent to the terminal because it is unreachable| + +## Stop Listening Device{#7} + +`StopListeningDevice` + +This operation interrupts the connection, stops listening to transaction events and resets the connection with the device + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` + +## Sale Reversal{#8} + +`SaleReversal` + +A sale Reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|A Financial Response object| + + +## Refund{#9} + +`Refund` + +A refund initiates a refund operation to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `refundOptions` Required
[*RefundOptions*](javascriptobjects.md#24) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|A Financial Response object| + + +## Refund Reversal{#10} + +`RefundReversal` + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a refundReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Reversal Response**|A Financial Response object| + + + +## Tokenize Card{#11} + +`TokenizeCard` + +Returns a token for the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|A Financial Response object| + + +## Card Pan{#12} + +`CardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|A Financial Response object| + + +## Stop Current Transaction{#13} + +`StopCurrentTransaction` + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of a payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` + +This method sends the merchant or customer receipt to the terminal for printing. The format of the HTML data, passed to the method or stored in the url, must follow this format: Html Print Format. + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific Status object that describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object| + +## Update{#16} + +`Update` + +Triggers a terminal software and config update + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A Financial Response object| + From a9f63fc2e281c5f11d02f2daaf883e15380a778b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 12:08:38 +0200 Subject: [PATCH 012/115] chore: testing staging deployment Co-authored-by: ecunado --- src/pages/cpdocs.js | 2 +- src/pages/index.js | 2 +- static/img/logo-header.svg | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 static/img/logo-header.svg diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 9e4b3a2..e540bbd 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -115,7 +115,7 @@ function Header() { padding: '80px', width: '100%' }}> - Logo + Logo

- Logo + Logo

+ + + + + + + + + + + + + + + + + From 1ea4d27c138a137b867026bf175cc5184ab4f4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 12:14:50 +0200 Subject: [PATCH 013/115] chore: testing staging deployment WIP Co-authored-by: ecunado --- src/pages/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/index.js b/src/pages/index.js index 4639322..0c9756c 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -24,7 +24,7 @@ function Header() { padding: '50px', width: '100%' }}> - Logo + Logo

Date: Wed, 21 Sep 2022 12:22:03 +0200 Subject: [PATCH 014/115] feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado --- android/androidmigrationguide.md | 230 ++++++++++++++++++++++--------- android/androidobjects.md | 16 +++ android/androidtransactions.md | 100 +++++++------- 3 files changed, 230 insertions(+), 116 deletions(-) diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 5c56224..4e3f46a 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -3,119 +3,225 @@ sidebar_position: 3 id: androidmigrationguide --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; -# Migration from 5.X{#1} +# Migration from 6.X to 7.X{#1} +The new version 7.X of our Android SDK introduces the next changes: +- Removed the **Required** Interface and created [3 new Interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +- The [operations described below](androidmigrationguide.md#3), return the [OperationStartResult](androidobjects.md#operation-start-result) object instead of a `boolean`. +- The new Duplicate Check service **is enabled by default**. To disable it, please check this [section](androidmigrationguide.md#4). +- `deviceCapabilities` event of CardBrandDisplay Interface has been renamed. +## 1. New integration Interfaces -Version 6.0.0 introduces a well defined, typed, way of passing extra values, options, parameters or flags to the financial transactions. +For an easier integration with our SDK, we have created 3 interfaces, which have each of the mandatory events to be implemented correctly: -We have unified all the extra and optional parameters in an Options object. Different operations have different options. +- **SmartposRequired**: Android Native Integration (PAX/Telpo) +- **MposRequired**: for Bluetooth integrations (HiLite) +- **PosRequired**: For integrations that include both -**1. For a [Sale](androidtransactions.md#2) or [Sale and Tokenize](androidtransactions.md#3) operation, please see [SaleOptions](androidobjects.md#4)** +The changes required in each of the scenarios are described below. -If you use a customer reference: + + +### Android Native Integration + +#### Older Implementation (Android SDK 6.X) + + ```java -options.setCustomerReference("Your customer reference"); +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { ``` -If you need Multi MID / Custom merchant Authentication: + + + ```java - MerchantAuth auth = new MerchantAuth(); - Credential credential = new Credential(); - //Optionally - credential.setAcquirer(YOUR_ACQUIRER); - //Optionally - credential.setMerchantId(mid); - //Optionally - credential.setTerminalId(tid); - //Add as many credentials as Acquirers your merchant have agreements with - auth.add(credential); - options.setMerchantAuth(auth); +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransact { ``` -If you need to enable pin bypass: + + + +#### Current Implementation (Android SDK 7.X) + + ```java -options.setPinBypass(true); +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { ``` -If you want to specify the budget period **Only available for SureSwipe**: + + + + ```java -options.setBudgetNumber(YOUR_BUDGET_NUMBER); +class KotlinClient: Events.SmartposRequired { ``` -If you want to specify tip options **Only available for PAX and Telpo terminals**: + + + +### Bluetooth Integration + +#### Older Implementation (Android SDK 6.X) + + ```java -TipConfiguration config = new TipConfiguration(); - //Optionally - config.setHeaderName(HEADER); - //Optionally - config.setFooter(FOOTER); - //Optionally - config.setEnterAmountEnabled(true); - //Optionally - config.setSkipEnabled(true); - //Optionally - config.setTipPercentages(percentages); - - options.setTipConfiguration(config); +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { ``` -Alternatively, you can set the tip amount directly: + + + ```java - options.setTipConfiguration(new TipConfiguration(AMOUNT)); +class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { ``` -Finally: + + + +#### Current Implementation (Android SDK 7.X) + + ```java -api.sale(amount, currency, options); +public class JavaClient implements + Events.MposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady ``` -**2. Similar to SaleOptions, but with less possible parameters, for a [Refund](androidtransactions.md#5) operation, please see [RefundOptions](androidobjects.md#6)** + -If you use a customer reference: + ```java -options.setCustomerReference("Your customer reference"); +class KotlinClient: Events.MposRequired { ``` -If you need Multi MID / Custom merchant Authentication: + + + +### Bluetooth and Android Native Integration + +#### Older Implementation (Android SDK 6.X) + + ```java - MerchantAuth auth = new MerchantAuth(); - Credential credential = new Credential(); - //Optionally - credential.setAcquirer(YOUR_ACQUIRER); - //Optionally - credential.setMerchantId(mid); - //Optionally - credential.setTerminalId(tid); - //Add as many credentials as Acquirers your merchant have agreements with - auth.add(credential); - options.setMerchantAuth(auth); +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { ``` -If you need to enable pin bypass: + + + ```java -options.setPinBypass(true); +class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { ``` -Finally: + + + +#### Current Implementation (Android SDK 7.X) + + ```java - api.refund(amount, currency, options); +public class JavaClient implements + Events.PosRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady ``` -**3. For the rest of operations, please see [Options](androidobjects.md#7)** + -If you use a customer reference: + ```java -options.setCustomerReference("Your customer reference"); +class KotlinClient: Events.PosRequired { ``` + + + + + +## 2. [OperationStartResult](androidobjects.md#operation-start-result) class is returned now on Hapi Operations{#3} + +With the aim of improving the information on our customers' transactions, now, Hapi object returns this class instead of a boolean. The methods that are affected by this change, and that should be modified for a correct implementation are the following: + +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disable Duplicate Check service{#4} + +By default our Duplicate Check service is enabled. To disable the Duplicate Check service, set the `checkDuplicate` field to false for the corresponding operations, as in the following example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +This step applies for the followings operations: +- [Sale](androidtransactions.md#2) and [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. Renamed event deviceCapabilities of CardBrandDisplay Interface + +Changed the name of the event `deviceCapabilities` of CardBrandDisplay Interface. Now `deviceCapabilities` is called `supportedCardBrands`. + +Check [here](androideventlisteners.md#cardBrandDisplay) all the necessary information. \ No newline at end of file diff --git a/android/androidobjects.md b/android/androidobjects.md index 5487bdc..0176d5d 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -646,6 +646,22 @@ options.setChannel(MoToChannel.MO); options.setChannel(MoToChannel.TO); ``` + +## Operation Start Result + +`OperationStartResult` Object + +Object that contains information about the operation performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` The operation has started. | +| `transactionReference`
*String* | Identification of the operation throughout its life cycle. | +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + ## Optional Transaction Parameters `OptionalParameters` Object diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 2cae25c..e65da9d 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -3,15 +3,15 @@ sidebar_position: 5 id: androidtransactions --- -# Transaction Types +# Transactions -## Sale{#2} +## Sale{#2} -`Sale` Method +`Sale` -A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the **amount** and **currency**. +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. **Parameters** @@ -65,14 +65,14 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| ## Sale And Tokenize Card{#3} -`saleAndTokenizeCard` Method +`saleAndTokenizeCard` -A [sale](#2) operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) **Parameters** @@ -90,7 +90,7 @@ A [sale](#2) operation which also returns a card token. This functionality is no api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); //Initiate a sale for 10.00 in Great British Pounds with tipping configuration -//This feature is not available for HiLite devices +//This feature is not available for HiLite & Hi5 devices TipConfiguration tipConfiguration = new TipConfiguration(); tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); tipConfiguration.setAmount(new BigInteger("1000")); @@ -125,13 +125,13 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## Sale Reversal +## Sale Reversal{#4} -`saleReversal` Method +`saleReversal` A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. @@ -143,7 +143,7 @@ A sale reversal, also called sale VOID allows the user to reverse a previous sal | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionID` Required
*String* | Id of the original sale transaction| -| `options`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store all the customization options for the transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| **Code example** @@ -173,12 +173,12 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| ## Refund{#5} -`refund` Method +`refund` A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. @@ -190,7 +190,7 @@ A refund operation moves funds from the merchant account to the cardholder´s cr | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| **Code example** @@ -220,12 +220,12 @@ Invoked when the terminal finishes processing the transaction | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## Refund reversal +## Refund reversal{#6} -`refundReversal` Method +`refundReversal` A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. @@ -237,7 +237,7 @@ A refund reversal, also called refund VOID allows the merchant to reverse a prev | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionID` Required
*String* | transaction id of the original refund| -| `options`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store all the customization options for the transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| **Code example** @@ -267,16 +267,15 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## MoTo Sale +## MoTo Sale{#7} -`MoToSale` Method +`MoToSale` Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. -Calling this operation will trigger the MOTO input form on the payment terminal, the MOTO form requires the merchant to enter the card number, expiry date and check value (CVV) of the card before processing the transaction. **Parameters** @@ -300,7 +299,7 @@ api.motoSale(new BigInteger("1000"), Currency.EUR, options); [**currentTransactionStatus**](androideventlisteners.md#14) -Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). *** @@ -313,17 +312,15 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the gateway.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## MoTo Refund +## MoTo Refund{#8} -`moToRefund` Method +`moToRefund` -A Mail Order/Telephone Order (MOTO) refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. - -Calling this operation will trigger the MOTO input form on the payment terminal, the MOTO form requires the merchant to enter the card number, expiry date and check value (CVV) of the card before processing the transaction. +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. **Parameters** @@ -333,7 +330,7 @@ Calling this operation will trigger the MOTO input form on the payment terminal, | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `originalTransactionId`
*String* | If present, it links the refund with a previous sale. It effectively limits the maximum amount which can be refunded to the amount of the previous sale.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| | `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| **Code example** @@ -361,12 +358,12 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the gateway.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## MoTo Reversal +## MoTo Reversal{#9} -`moToReversal` Method +`moToReversal` A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. @@ -404,14 +401,14 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the gateway.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| ## Signature result -`signatureResult` Method +`signatureResult` -A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. **Parameters** @@ -446,16 +443,16 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| ## Tip Adjustment -`TipAdjustment` Method +`TipAdjustment` A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. -Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. Dependencies: The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. @@ -494,7 +491,6 @@ Observable.fromCallable(new Callable() { **Returns** -[**FinancialStatus**](androidobjects.md#34) Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : @@ -504,18 +500,18 @@ Result of the tip adjustment transaction, it returns a FinancialStatus, the poss If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. -## Tokenize Card +## Tokenize Card{#12} -`tokenizeCard` Method +`tokenizeCard` -Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `options`
[*Options*](androidobjects.md#7) | An object to store all the customization options for the transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| **Code example** @@ -540,16 +536,12 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| - +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| -## Card PAN -`cardPan` Method +## Card PAN{#13} -:::warning -This transaction type will ONLY work on PAX/Telpo devices. On HiLite payment terminals it is not available. -::: +`cardPan` A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. @@ -558,7 +550,7 @@ A cardPan request will return the full PAN of the card being swiped, dipped or t | Parameter | Notes | | ----------- | ----------- | -| `options`
[*Options*](androidobjects.md#7) | An object to store all the customization options for the transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| **Code example** @@ -583,4 +575,4 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the terminal.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| From d347c3348cea2ec15d830be63756d020fa6f2c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Wed, 21 Sep 2022 12:29:13 +0200 Subject: [PATCH 015/115] -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7d6a56c..23f8266 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -33,7 +33,7 @@ jobs: cache: yarn - uses: webfactory/ssh-agent@v0.5.0 with: - ssh-private-key: ${{ secrets.CARD_PRESENT_DEV_PRIVATE_KEY }} + ssh-private-key: ${{ secrets.CARD_PRESENT_PRIVATE_KEY }} if: github.ref == 'refs/heads/main' - uses: webfactory/ssh-agent@v0.5.0 with: From bedec8141468b6cdc6b284d788241a437018044d Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 23 Sep 2022 10:47:07 +0200 Subject: [PATCH 016/115] Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 --- windows/windowsreleasenotes.md | 12 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 360 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 1951 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 513 +++++ .../windowsreleasenotes.md | 48 + .../windowstransactions.md | 558 +++++ .../version-Windows SDK 3.2.5-sidebars.json | 8 + windows_versions.json | 1 + 12 files changed, 3834 insertions(+), 1 deletion(-) create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.2.5/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 3.2.5-sidebars.json diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index fe20688..7a7605b 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -9,9 +9,19 @@ id: windowsreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 3.2.5 +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + ## 3.2.4 **Fixes:** -- `SignatureResult` method. Signature result is always true no matter what is passed to the method +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. ## 3.2.3 **Fixes:** diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md new file mode 100644 index 0000000..09b7ce9 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md @@ -0,0 +1,360 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.UseDevice(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.UseDevice(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set parameter + +`SetParameter` Method + +Allows developers to optionally change several internal parameters of the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| +| `value` Required
*String* | New value of the parameter.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Changes the bluetooth name of card reader +api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md new file mode 100644 index 0000000..5d410ec --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md new file mode 100644 index 0000000..f58da30 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md @@ -0,0 +1,1951 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void **[*deviceDiscoveryFinished*](#13)**(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + // Put the name of your device, it is the composition of: serial number - device model. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void **[*deviceDiscoveryFinished*](#13)**(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md new file mode 100644 index 0000000..f4ab24e --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md @@ -0,0 +1,513 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md new file mode 100644 index 0000000..7a7605b --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 3.2.5 +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowstransactions.md new file mode 100644 index 0000000..ad1653b --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowstransactions.md @@ -0,0 +1,558 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, dic); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Requiredv*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| diff --git a/windows_versioned_sidebars/version-Windows SDK 3.2.5-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 3.2.5-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 3.2.5-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index c86d2c9..ede2795 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 3.2.5", "Windows SDK 3.2.4", "Windows SDK 3.2.0" ] From e4dd443c8c9dbd2d72f428ffb49621076ba09430 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Fri, 23 Sep 2022 10:49:42 +0200 Subject: [PATCH 017/115] SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos --- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 623 +++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 92 + .../javascriptreleasenotes.md | 34 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 220 + .../javascripttransactiontypes.md | 447 ++ ...version-Javascript SDK 6.2.0-sidebars.json | 8 + javascript_versions.json | 1 + package-lock.json | 4821 ++++++++--------- package.json | 4 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.10.0/restdownloads.md | 10 + .../version-REST API 2.10.0/restendpoints.md | 273 + .../restintroduction.md | 50 + .../version-REST API 2.10.0/restobjects.md | 616 +++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 33 + .../version-REST API 2.10.0/restsandbox.md | 44 + .../version-REST API 2.10.0-sidebars.json | 8 + restapi_versions.json | 2 +- 22 files changed, 4788 insertions(+), 2627 deletions(-) create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-Javascript SDK 6.2.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.10.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.10.0-sidebars.json diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md new file mode 100644 index 0000000..2b68489 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md new file mode 100644 index 0000000..0a0e6b1 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -0,0 +1,623 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference" +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Flag to select the duplicate check payments flow.| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Flag to select the duplicate check payments flow.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md new file mode 100644 index 0000000..23133c6 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md @@ -0,0 +1,92 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example 0821032395-PAXA920. If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable environmentIsDevelopment to true otherwise change it to false. + +4)Open the html file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptmethods.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md new file mode 100644 index 0000000..912b5d6 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md @@ -0,0 +1,34 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 6.2.0 + +**Features**: +- New "Duplicate check" flag which enables the duplicate payments checking transaction flow. + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptsandbox.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..b6241c0 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptterminalmanagement.md @@ -0,0 +1,220 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascripttransactiontypes.md new file mode 100644 index 0000000..9a7d0c4 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascripttransactiontypes.md @@ -0,0 +1,447 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleAndTokenization('1000', 'USD', saleOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale and Tokenization Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +Handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction Status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + diff --git a/javascript_versioned_sidebars/version-Javascript SDK 6.2.0-sidebars.json b/javascript_versioned_sidebars/version-Javascript SDK 6.2.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-Javascript SDK 6.2.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index dea41cb..5b5ef55 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "Javascript SDK 6.2.0", "JavaScript SDK 6.1.0", "JavaScript SDK 6.0.1" ] diff --git a/package-lock.json b/package-lock.json index 75dc3a3..1af454c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "0.0.0", "dependencies": { "@cmfcmf/docusaurus-search-local": "^0.9.4", - "@docusaurus/core": "^2.0.0-beta.21", - "@docusaurus/preset-classic": "^2.0.0-beta.21", + "@docusaurus/core": "^2.0.0-rc.1", + "@docusaurus/preset-classic": "^2.0.0-rc.1", "@easyops-cn/docusaurus-search-local": "^0.26.1", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", @@ -206,39 +206,39 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", - "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "dependencies": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -262,12 +262,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "dependencies": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.18.13", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "engines": { @@ -275,11 +275,11 @@ } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", - "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dependencies": { - "@jridgewell/set-array": "^1.0.0", + "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" }, @@ -288,35 +288,35 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" }, @@ -336,17 +336,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz", - "integrity": "sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-member-expression-to-functions": "^7.17.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -356,12 +356,12 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz", - "integrity": "sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" }, "engines": { "node": ">=6.9.0" @@ -371,14 +371,12 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz", + "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==", "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", @@ -397,216 +395,228 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", - "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dependencies": { - "@babel/types": "^7.18.2" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", "dependencies": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", "dependencies": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -649,12 +659,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { "node": ">=0.8.0" } @@ -662,7 +672,7 @@ "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" } @@ -679,9 +689,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", - "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -690,11 +700,11 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.17.12.tgz", - "integrity": "sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -704,13 +714,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz", - "integrity": "sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", + "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -720,12 +730,13 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz", - "integrity": "sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -736,12 +747,12 @@ } }, "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", - "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -751,12 +762,12 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz", - "integrity": "sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -767,11 +778,11 @@ } }, "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -782,11 +793,11 @@ } }, "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz", - "integrity": "sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -797,11 +808,11 @@ } }, "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz", - "integrity": "sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -812,11 +823,11 @@ } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz", - "integrity": "sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -827,11 +838,11 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz", - "integrity": "sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -842,11 +853,11 @@ } }, "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -857,15 +868,15 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz", - "integrity": "sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.17.12" + "@babel/plugin-transform-parameters": "^7.18.8" }, "engines": { "node": ">=6.9.0" @@ -875,11 +886,11 @@ } }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -890,12 +901,12 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz", - "integrity": "sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -906,12 +917,12 @@ } }, "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz", - "integrity": "sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -921,13 +932,13 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz", - "integrity": "sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -938,12 +949,12 @@ } }, "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz", - "integrity": "sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=4" @@ -1011,11 +1022,11 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz", - "integrity": "sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1036,11 +1047,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz", - "integrity": "sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1144,11 +1155,11 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", - "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1158,11 +1169,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz", - "integrity": "sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1172,13 +1183,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz", - "integrity": "sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-remap-async-to-generator": "^7.16.8" + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1188,11 +1199,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1202,11 +1213,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.17.12.tgz", - "integrity": "sha512-jw8XW/B1i7Lqwqj2CbrViPcZijSxfguBWZP2aN59NHgxUyO/OcO1mfdCxH13QhN5LbWhPkX+f+brKGhZTiqtZQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1216,17 +1227,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.17.12.tgz", - "integrity": "sha512-cvO7lc7pZat6BsvH6l/EGaI8zpl8paICaoGk+7x7guvtfak/TbIf66nYmJOH13EuG0H+Xx3M+9LQDtSvZFKXKw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", "globals": "^11.1.0" }, "engines": { @@ -1237,11 +1248,11 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz", - "integrity": "sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1251,11 +1262,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz", - "integrity": "sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1265,12 +1276,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1280,11 +1291,11 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz", - "integrity": "sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1294,12 +1305,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1309,11 +1320,11 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz", - "integrity": "sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1323,13 +1334,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", "dependencies": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1339,11 +1350,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz", - "integrity": "sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1353,11 +1364,11 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1367,12 +1378,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz", - "integrity": "sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1382,22 +1393,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-amd/node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dependencies": { - "object.assign": "^4.1.0" - } - }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz", - "integrity": "sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-simple-access": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1407,23 +1410,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs/node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dependencies": { - "object.assign": "^4.1.0" - } - }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.0.tgz", - "integrity": "sha512-vwKpxdHnlM5tIrRt/eA0bzfbi7gUBLN08vLu38np1nZevlPySRe6yvuATJB5F/WPJ+ur4OXwpVYq9+BsxqAQuQ==", - "dependencies": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-identifier": "^7.16.7", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { @@ -1433,21 +1428,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs/node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dependencies": { - "object.assign": "^4.1.0" - } - }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz", - "integrity": "sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1457,12 +1444,12 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz", - "integrity": "sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1472,11 +1459,11 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz", - "integrity": "sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1486,12 +1473,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1501,11 +1488,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz", - "integrity": "sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1515,11 +1502,11 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1543,11 +1530,11 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", - "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1557,15 +1544,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz", - "integrity": "sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz", + "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-jsx": "^7.17.12", - "@babel/types": "^7.17.12" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" @@ -1575,11 +1562,11 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", - "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.16.7" + "@babel/plugin-transform-react-jsx": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1589,12 +1576,12 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", - "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1604,11 +1591,11 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz", - "integrity": "sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "regenerator-transform": "^0.15.0" }, "engines": { @@ -1619,11 +1606,11 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz", - "integrity": "sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1633,15 +1620,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz", - "integrity": "sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", + "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", "semver": "^6.3.0" }, "engines": { @@ -1660,11 +1647,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1674,12 +1661,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz", - "integrity": "sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1689,11 +1676,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1703,11 +1690,11 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz", - "integrity": "sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1717,11 +1704,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz", - "integrity": "sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1731,13 +1718,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.4.tgz", - "integrity": "sha512-l4vHuSLUajptpHNEOUDEGsnpl9pfRLsN1XUoDQDD/YBuXTM+v37SHGS+c6n4jdcZy96QtuUuSvZYMLSSsjH8Mw==", + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz", + "integrity": "sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-typescript": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-typescript": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1747,11 +1734,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1761,12 +1748,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1776,37 +1763,37 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.2.tgz", - "integrity": "sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==", - "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-async-generator-functions": "^7.17.12", - "@babel/plugin-proposal-class-properties": "^7.17.12", - "@babel/plugin-proposal-class-static-block": "^7.18.0", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.17.12", - "@babel/plugin-proposal-json-strings": "^7.17.12", - "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.18.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-private-methods": "^7.17.12", - "@babel/plugin-proposal-private-property-in-object": "^7.17.12", - "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.17.12", + "@babel/plugin-syntax-import-assertions": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -1816,43 +1803,43 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.17.12", - "@babel/plugin-transform-async-to-generator": "^7.17.12", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.17.12", - "@babel/plugin-transform-classes": "^7.17.12", - "@babel/plugin-transform-computed-properties": "^7.17.12", - "@babel/plugin-transform-destructuring": "^7.18.0", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.17.12", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.18.1", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.17.12", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.18.0", - "@babel/plugin-transform-modules-commonjs": "^7.18.2", - "@babel/plugin-transform-modules-systemjs": "^7.18.0", - "@babel/plugin-transform-modules-umd": "^7.18.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", - "@babel/plugin-transform-new-target": "^7.17.12", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.17.12", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.18.0", - "@babel/plugin-transform-reserved-words": "^7.17.12", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.17.12", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.18.2", - "@babel/plugin-transform-typeof-symbol": "^7.17.12", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.2", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", "core-js-compat": "^3.22.1", "semver": "^6.3.0" }, @@ -1887,16 +1874,16 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.17.12.tgz", - "integrity": "sha512-h5U+rwreXtZaRBEQhW1hOJLMq8XNJBQ/9oymXiCXTuT/0uOwpbT0gUt+sXeOqoXBgNuUKI7TaObVwoEyWkpFgA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-react-display-name": "^7.16.7", - "@babel/plugin-transform-react-jsx": "^7.17.12", - "@babel/plugin-transform-react-jsx-development": "^7.16.7", - "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1906,13 +1893,13 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.17.12.tgz", - "integrity": "sha512-S1ViF8W2QwAKUGJXxP9NAfNaqGDdEBJKpYkxHf5Yy2C4NPPzXGeR3Lhk7G8xJaaLcFTRfNjVbtbVtm8Gb0mqvg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -1922,9 +1909,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz", - "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -1933,9 +1920,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz", - "integrity": "sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz", + "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==", "dependencies": { "core-js-pure": "^3.20.2", "regenerator-runtime": "^0.13.4" @@ -1945,31 +1932,31 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", - "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.0", - "@babel/types": "^7.18.2", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1978,11 +1965,12 @@ } }, "node_modules/@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2023,61 +2011,85 @@ } }, "node_modules/@docsearch/css": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.1.0.tgz", - "integrity": "sha512-bh5IskwkkodbvC0FzSg1AxMykfDl95hebEKwxNoq4e5QaGzOXSBgW8+jnMFZ7JU4sTBiB04vZWoUSzNrPboLZA==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.2.1.tgz", + "integrity": "sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==" }, "node_modules/@docsearch/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.1.0.tgz", - "integrity": "sha512-bjB6ExnZzf++5B7Tfoi6UXgNwoUnNOfZ1NyvnvPhWgCMy5V/biAtLL4o7owmZSYdAKeFSvZ5Lxm0is4su/dBWg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.2.1.tgz", + "integrity": "sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==", "dependencies": { - "@algolia/autocomplete-core": "1.6.3", - "@docsearch/css": "3.1.0", + "@algolia/autocomplete-core": "1.7.1", + "@algolia/autocomplete-preset-algolia": "1.7.1", + "@docsearch/css": "3.2.1", "algoliasearch": "^4.0.0" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", "react": ">= 16.8.0 < 19.0.0", "react-dom": ">= 16.8.0 < 19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.6.3.tgz", - "integrity": "sha512-dqQqRt01fX3YuVFrkceHsoCnzX0bLhrrg8itJI1NM68KjrPYQPYsE+kY8EZTCM4y8VDnhqJErR73xe/ZsV+qAA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.7.1.tgz", + "integrity": "sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==", + "dependencies": { + "@algolia/autocomplete-shared": "1.7.1" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.1.tgz", + "integrity": "sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==", "dependencies": { - "@algolia/autocomplete-shared": "1.6.3" + "@algolia/autocomplete-shared": "1.7.1" + }, + "peerDependencies": { + "@algolia/client-search": "^4.9.1", + "algoliasearch": "^4.9.1" } }, "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.6.3.tgz", - "integrity": "sha512-UV46bnkTztyADFaETfzFC5ryIdGVb2zpAoYgu0tfcuYWjhg1KbLXveFffZIrGVoboqmAk1b+jMrl6iCja1i3lg==" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.1.tgz", + "integrity": "sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==" }, "node_modules/@docusaurus/core": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.21.tgz", - "integrity": "sha512-qysDMVp1M5UozK3u/qOxsEZsHF7jeBvJDS+5ItMPYmNKvMbNKeYZGA0g6S7F9hRDwjIlEbvo7BaX0UMDcmTAWA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.1.tgz", + "integrity": "sha512-Prd46TtZdiixlTl8a+h9bI5HegkfREjSNkrX2rVEwJZeziSz4ya+l7QDnbnCB2XbxEG8cveFo/F9q5lixolDtQ==", "dependencies": { - "@babel/core": "^7.18.2", - "@babel/generator": "^7.18.2", + "@babel/core": "^7.18.6", + "@babel/generator": "^7.18.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.18.2", - "@babel/preset-env": "^7.18.2", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.17.12", - "@babel/runtime": "^7.18.3", - "@babel/runtime-corejs3": "^7.18.3", - "@babel/traverse": "^7.18.2", - "@docusaurus/cssnano-preset": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", + "@babel/plugin-transform-runtime": "^7.18.6", + "@babel/preset-env": "^7.18.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@babel/runtime": "^7.18.6", + "@babel/runtime-corejs3": "^7.18.6", + "@babel/traverse": "^7.18.8", + "@docusaurus/cssnano-preset": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", - "@slorber/static-site-generator-webpack-plugin": "^4.0.4", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.2.1", "autoprefixer": "^10.4.7", "babel-loader": "^8.2.5", @@ -2090,10 +2102,10 @@ "combine-promises": "^1.1.0", "commander": "^5.1.0", "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.22.7", + "core-js": "^3.23.3", "css-loader": "^6.7.1", "css-minimizer-webpack-plugin": "^4.0.0", - "cssnano": "^5.1.9", + "cssnano": "^5.1.12", "del": "^6.1.1", "detect-port": "^1.3.0", "escape-html": "^1.0.3", @@ -2106,7 +2118,7 @@ "import-fresh": "^3.3.0", "leven": "^3.1.0", "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.6.0", + "mini-css-extract-plugin": "^2.6.1", "postcss": "^8.4.14", "postcss-loader": "^7.0.0", "prompts": "^2.4.2", @@ -2117,19 +2129,18 @@ "react-router": "^5.3.3", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.3", - "remark-admonitions": "^1.2.1", "rtl-detect": "^1.0.4", "semver": "^7.3.7", "serve-handler": "^6.1.3", "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.1", + "terser-webpack-plugin": "^5.3.3", "tslib": "^2.4.0", "update-notifier": "^5.1.0", "url-loader": "^4.1.1", "wait-on": "^6.0.1", - "webpack": "^5.72.1", + "webpack": "^5.73.0", "webpack-bundle-analyzer": "^4.5.0", - "webpack-dev-server": "^4.9.0", + "webpack-dev-server": "^4.9.3", "webpack-merge": "^5.8.0", "webpackbar": "^5.0.2" }, @@ -2192,14 +2203,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@docusaurus/core/node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dependencies": { - "object.assign": "^4.1.0" - } - }, "node_modules/@docusaurus/core/node_modules/boxen": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", @@ -2469,11 +2472,11 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.21.tgz", - "integrity": "sha512-fhTZrg1vc6zYYZIIMXpe1TnEVGEjqscBo0s1uomSwKjjtMgu7wkzc1KKJYY7BndsSA+fVVkZ+OmL/kAsmK7xxw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.1.tgz", + "integrity": "sha512-MCJ6rRmlqLmlCsZIoIxOxDb0rYzIPEm9PYpsBW+CGNnbk+x8xK+11hnrxzvXHqDRNpxrq3Kq2jYUmg/DkqE6vg==", "dependencies": { - "cssnano-preset-advanced": "^5.3.5", + "cssnano-preset-advanced": "^5.3.8", "postcss": "^8.4.14", "postcss-sort-media-queries": "^4.2.1", "tslib": "^2.4.0" @@ -2483,9 +2486,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.21.tgz", - "integrity": "sha512-HTFp8FsSMrAj7Uxl5p72U+P7rjYU/LRRBazEoJbs9RaqoKEdtZuhv8MYPOCh46K9TekaoquRYqag2o23Qt4ggA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.1.tgz", + "integrity": "sha512-wIWseCKko1w/WARcDjO3N/XoJ0q/VE42AthP0eNAfEazDjJ94NXbaI6wuUsuY/bMg6hTKGVIpphjj2LoX3g6dA==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.4.0" @@ -2495,14 +2498,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.21.tgz", - "integrity": "sha512-AI+4obJnpOaBOAYV6df2ux5Y1YJCBS+MhXFf0yhED12sVLJi2vffZgdamYd/d/FwvWDw6QLs/VD2jebd7P50yQ==", - "dependencies": { - "@babel/parser": "^7.18.3", - "@babel/traverse": "^7.18.2", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.1.tgz", + "integrity": "sha512-tdNeljdilXCmhbaEND3SAgsqaw/oh7v9onT5yrIrL26OSk2AFwd+MIi4R8jt8vq33M0R4rz2wpknm0fQIkDdvQ==", + "dependencies": { + "@babel/parser": "^7.18.8", + "@babel/traverse": "^7.18.8", + "@docusaurus/logger": "2.0.1", + "@docusaurus/utils": "2.0.1", "@mdx-js/mdx": "^1.6.22", "escape-html": "^1.0.3", "file-loader": "^6.2.0", @@ -2512,9 +2515,10 @@ "remark-emoji": "^2.2.0", "stringify-object": "^3.3.0", "tslib": "^2.4.0", + "unified": "^9.2.2", "unist-util-visit": "^2.0.3", "url-loader": "^4.1.1", - "webpack": "^5.72.1" + "webpack": "^5.73.0" }, "engines": { "node": ">=16.14" @@ -2524,43 +2528,76 @@ "react-dom": "^16.8.4 || ^17.0.0" } }, + "node_modules/@docusaurus/mdx-loader/node_modules/unified": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", + "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@docusaurus/module-type-aliases": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.21.tgz", - "integrity": "sha512-gRkWICgQZiqSJgrwRKWjXm5gAB+9IcfYdUbCG0PRPP/G8sNs9zBIOY4uT4Z5ox2CWFEm44U3RTTxj7BiLVMBXw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.1.tgz", + "integrity": "sha512-f888ylnxHAM/3T8p1lx08+lTc6/g7AweSRfRuZvrVhHXj3Tz/nTTxaP6gPTGkJK7WLqTagpar/IGP6/74IBbkg==", "dependencies": { - "@docusaurus/types": "2.0.0-beta.21", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/types": "2.0.1", + "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", - "react-helmet-async": "*" + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, + "node_modules/@docusaurus/module-type-aliases/node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.21.tgz", - "integrity": "sha512-IP21yJViP3oBmgsWBU5LhrG1MZXV4mYCQSoCAboimESmy1Z11RCNP2tXaqizE3iTmXOwZZL+SNBk06ajKCEzWg==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", - "cheerio": "^1.0.0-rc.11", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.1.tgz", + "integrity": "sha512-/4ua3iFYcpwgpeYgHnhVGROB/ybnauLH2+rICb4vz/+Gn1hjAmGXVYq1fk8g49zGs3uxx5nc0H5bL9P0g977IQ==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^10.1.0", "lodash": "^4.17.21", "reading-time": "^1.5.0", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", "unist-util-visit": "^2.0.3", "utility-types": "^3.10.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" }, "engines": { "node": ">=16.14" @@ -2571,24 +2608,26 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.21.tgz", - "integrity": "sha512-aa4vrzJy4xRy81wNskyhE3wzRf3AgcESZ1nfKh8xgHUkT7fDTZ1UWlg50Jb3LBCQFFyQG2XQB9N6llskI/KUnw==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.1.tgz", + "integrity": "sha512-2qeBWRy1EjgnXdwAO6/csDIS1UVNmhmtk/bQ2s9jqjpwM8YVgZ8QVdkxFAMWXgZWDQdwWwdP1rnmoEelE4HknQ==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "@types/react-router-config": "^5.0.6", "combine-promises": "^1.1.0", "fs-extra": "^10.1.0", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", "utility-types": "^3.10.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" }, "engines": { "node": ">=16.14" @@ -2599,18 +2638,18 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.21.tgz", - "integrity": "sha512-DmXOXjqNI+7X5hISzCvt54QIK6XBugu2MOxjxzuqI7q92Lk/EVdraEj5mthlH8IaEH/VlpWYJ1O9TzLqX5vH2g==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.1.tgz", + "integrity": "sha512-6apSVeJENnNecAH5cm5VnRqR103M6qSI6IuiP7tVfD5H4AWrfDNkvJQV2+R2PIq3bGrwmX4fcXl1x4g0oo7iwA==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "fs-extra": "^10.1.0", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" }, "engines": { "node": ">=16.14" @@ -2621,12 +2660,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.21.tgz", - "integrity": "sha512-P54J4q4ecsyWW0Jy4zbimSIHna999AfbxpXGmF1IjyHrjoA3PtuakV1Ai51XrGEAaIq9q6qMQkEhbUd3CffGAw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.1.tgz", + "integrity": "sha512-jpZBT5HK7SWx1LRQyv9d14i44vSsKXGZsSPA2ndth5HykHJsiAj9Fwl1AtzmtGYuBmI+iXQyOd4MAMHd4ZZ1tg==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", "fs-extra": "^10.1.0", "react-json-view": "^1.21.3", "tslib": "^2.4.0" @@ -2640,12 +2680,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.21.tgz", - "integrity": "sha512-+5MS0PeGaJRgPuNZlbd/WMdQSpOACaxEz7A81HAxm6kE+tIASTW3l8jgj1eWFy/PGPzaLnQrEjxI1McAfnYmQw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.1.tgz", + "integrity": "sha512-d5qb+ZeQcg1Czoxc+RacETjLdp2sN/TAd7PGN/GrvtijCdgNmvVAtZ9QgajBTG0YbJFVPTeZ39ad2bpoOexX0w==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" }, "engines": { @@ -2657,12 +2698,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.21.tgz", - "integrity": "sha512-4zxKZOnf0rfh6myXLG7a6YZfQcxYDMBsWqANEjCX77H5gPdK+GHZuDrxK6sjFvRBv4liYCrNjo7HJ4DpPoT0zA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.1.tgz", + "integrity": "sha512-qiRufJe2FvIyzICbkjm4VbVCI1hyEju/CebfDKkKh2ZtV4q6DM1WZG7D6VoQSXL8MrMFB895gipOM4BwdM8VsQ==", "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" }, "engines": { @@ -2674,15 +2716,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.21.tgz", - "integrity": "sha512-/ynWbcXZXcYZ6sT2X6vAJbnfqcPxwdGEybd0rcRZi4gBHq6adMofYI25AqELmnbBDxt0If+vlAeUHFRG5ueP7Q==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.1.tgz", + "integrity": "sha512-KcYuIUIp2JPzUf+Xa7W2BSsjLgN1/0h+VAz7D/C3RYjAgC5ApPX8wO+TECmGfunl/m7WKGUmLabfOon/as64kQ==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "fs-extra": "^10.1.0", "sitemap": "^7.1.1", "tslib": "^2.4.0" @@ -2696,21 +2739,22 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.21.tgz", - "integrity": "sha512-KvBnIUu7y69pNTJ9UhX6SdNlK6prR//J3L4rhN897tb8xx04xHHILlPXko2Il+C3Xzgh3OCgyvkoz9K6YlFTDw==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "@docusaurus/plugin-debug": "2.0.0-beta.21", - "@docusaurus/plugin-google-analytics": "2.0.0-beta.21", - "@docusaurus/plugin-google-gtag": "2.0.0-beta.21", - "@docusaurus/plugin-sitemap": "2.0.0-beta.21", - "@docusaurus/theme-classic": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-search-algolia": "2.0.0-beta.21" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.1.tgz", + "integrity": "sha512-nOoniTg46My1qdDlLWeFs55uEmxOJ+9WMF8KKG8KMCu5LAvpemMi7rQd4x8Tw+xiPHZ/sQzH9JmPTMPRE4QGPw==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/plugin-debug": "2.0.1", + "@docusaurus/plugin-google-analytics": "2.0.1", + "@docusaurus/plugin-google-gtag": "2.0.1", + "@docusaurus/plugin-sitemap": "2.0.1", + "@docusaurus/theme-classic": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-search-algolia": "2.0.1", + "@docusaurus/types": "2.0.1" }, "engines": { "node": ">=16.14" @@ -2733,31 +2777,35 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.21.tgz", - "integrity": "sha512-Ge0WNdTefD0VDQfaIMRRWa8tWMG9+8/OlBRd5MK88/TZfqdBq7b/gnCSaalQlvZwwkj6notkKhHx72+MKwWUJA==", - "dependencies": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-translations": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.1.tgz", + "integrity": "sha512-0jfigiqkUwIuKOw7Me5tqUM9BBvoQX7qqeevx7v4tkYQexPhk3VYSZo7aRuoJ9oyW5makCTPX551PMJzmq7+sw==", + "dependencies": { + "@docusaurus/core": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-translations": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "@mdx-js/react": "^1.6.22", - "clsx": "^1.1.1", + "clsx": "^1.2.1", "copy-text-to-clipboard": "^3.0.1", - "infima": "0.2.0-alpha.39", + "infima": "0.2.0-alpha.42", "lodash": "^4.17.21", "nprogress": "^0.2.0", "postcss": "^8.4.14", - "prism-react-renderer": "^1.3.3", + "prism-react-renderer": "^1.3.5", "prismjs": "^1.28.0", "react-router-dom": "^5.3.3", "rtlcss": "^3.5.0", - "tslib": "^2.4.0" + "tslib": "^2.4.0", + "utility-types": "^3.10.0" }, "engines": { "node": ">=16.14" @@ -2768,17 +2816,22 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.21.tgz", - "integrity": "sha512-fTKoTLRfjuFG6c3iwnVjIIOensxWMgdBKLfyE5iih3Lq7tQgkE7NyTGG9BKLrnTJ7cAD2UXdXM9xbB7tBf1qzg==", - "dependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "clsx": "^1.1.1", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.1.tgz", + "integrity": "sha512-I3b6e/ryiTQMsbES40cP0DRGnfr0E2qghVq+XecyMKjBPejISoSFEDn0MsnbW8Q26k1Dh/0qDH8QKDqaZZgLhA==", + "dependencies": { + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^1.2.1", "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^1.3.3", + "prism-react-renderer": "^1.3.5", "tslib": "^2.4.0", "utility-types": "^3.10.0" }, @@ -2791,21 +2844,21 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.21.tgz", - "integrity": "sha512-T1jKT8MVSSfnztSqeebUOpWHPoHKtwDXtKYE0xC99JWoZ+mMfv8AFhVSoSddn54jLJjV36mxg841eHQIySMCpQ==", - "dependencies": { - "@docsearch/react": "^3.1.0", - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-translations": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.1.tgz", + "integrity": "sha512-cw3NaOSKbYlsY6uNj4PgO+5mwyQ3aEWre5RlmvjStaz2cbD15Nr69VG8Rd/F6Q5VsCT8BvSdkPDdDG5d/ACexg==", + "dependencies": { + "@docsearch/react": "^3.1.1", + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-translations": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "algoliasearch": "^4.13.1", - "algoliasearch-helper": "^3.8.2", - "clsx": "^1.1.1", + "algoliasearch-helper": "^3.10.0", + "clsx": "^1.2.1", "eta": "^1.12.3", "fs-extra": "^10.1.0", "lodash": "^4.17.21", @@ -2821,9 +2874,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.21.tgz", - "integrity": "sha512-dLVT9OIIBs6MpzMb1bAy+C0DPJK3e3DNctG+ES0EP45gzEqQxzs4IsghpT+QDaOsuhNnAlosgJpFWX3rqxF9xA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.1.tgz", + "integrity": "sha512-v1MYYlbsdX+rtKnXFcIAn9ar0Z6K0yjqnCYS0p/KLCLrfJwfJ8A3oRJw2HiaIb8jQfk1WMY2h5Qi1p4vHOekQw==", "dependencies": { "fs-extra": "^10.1.0", "tslib": "^2.4.0" @@ -2833,16 +2886,17 @@ } }, "node_modules/@docusaurus/types": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.21.tgz", - "integrity": "sha512-/GH6Npmq81eQfMC/ikS00QSv9jNyO1RXEpNSx5GLA3sFX8Iib26g2YI2zqNplM8nyxzZ2jVBuvUoeODTIbTchQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.1.tgz", + "integrity": "sha512-o+4hAFWkj3sBszVnRTAnNqtAIuIW0bNaYyDwQhQ6bdz3RAPEq9cDKZxMpajsj4z2nRty8XjzhyufAAjxFTyrfg==", "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", "commander": "^5.1.0", - "history": "^4.9.0", "joi": "^17.6.0", "react-helmet-async": "^1.3.0", "utility-types": "^3.10.0", - "webpack": "^5.72.1", + "webpack": "^5.73.0", "webpack-merge": "^5.8.0" }, "peerDependencies": { @@ -2851,11 +2905,11 @@ } }, "node_modules/@docusaurus/utils": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.21.tgz", - "integrity": "sha512-M/BrVCDmmUPZLxtiStBgzpQ4I5hqkggcpnQmEN+LbvbohjbtVnnnZQ0vptIziv1w8jry/woY+ePsyOO7O/yeLQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.1.tgz", + "integrity": "sha512-u2Vdl/eoVwMfUjDCkg7FjxoiwFs/XhVVtNxQEw8cvB+qaw6QWyT73m96VZzWtUb1fDOefHoZ+bZ0ObFeKk9lMQ==", "dependencies": { - "@docusaurus/logger": "2.0.0-beta.21", + "@docusaurus/logger": "2.0.1", "@svgr/webpack": "^6.2.1", "file-loader": "^6.2.0", "fs-extra": "^10.1.0", @@ -2869,30 +2923,46 @@ "shelljs": "^0.8.5", "tslib": "^2.4.0", "url-loader": "^4.1.1", - "webpack": "^5.72.1" + "webpack": "^5.73.0" }, "engines": { "node": ">=16.14" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } } }, "node_modules/@docusaurus/utils-common": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.21.tgz", - "integrity": "sha512-5w+6KQuJb6pUR2M8xyVuTMvO5NFQm/p8TOTDFTx60wt3p0P1rRX00v6FYsD4PK6pgmuoKjt2+Ls8dtSXc4qFpQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.1.tgz", + "integrity": "sha512-kajCCDCXRd1HFH5EUW31MPaQcsyNlGakpkDoTBtBvpa4EIPvWaSKy7TIqYKHrZjX4tnJ0YbEJvaXfjjgdq5xSg==", "dependencies": { "tslib": "^2.4.0" }, "engines": { "node": ">=16.14" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } } }, "node_modules/@docusaurus/utils-validation": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.21.tgz", - "integrity": "sha512-6NG1FHTRjv1MFzqW//292z7uCs77vntpWEbZBHk3n67aB1HoMn5SOwjLPtRDjbCgn6HCHFmdiJr6euCbjhYolg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.1.tgz", + "integrity": "sha512-f14AnwFBy4/1A19zWthK+Ii80YDz+4qt8oPpK3julywXsheSxPBqgsND3LVBBvB2p3rJHvbo2m3HyB9Tco1JRw==", "dependencies": { - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "@docusaurus/logger": "2.0.1", + "@docusaurus/utils": "2.0.1", "joi": "^17.6.0", "js-yaml": "^4.1.0", "tslib": "^2.4.0" @@ -3115,24 +3185,46 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", - "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@mdx-js/mdx": { "version": "1.6.22", @@ -3792,116 +3884,16 @@ } }, "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", - "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", "dependencies": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", "eval": "^0.1.8", - "webpack-sources": "^1.4.3" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "engines": { - "node": "*" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/@slorber/static-site-generator-webpack-plugin/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" + "node": ">=14" } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { @@ -4233,9 +4225,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -4261,9 +4253,9 @@ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" }, "node_modules/@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", "dependencies": { "@types/node": "*" } @@ -4287,9 +4279,9 @@ } }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "node_modules/@types/node": { "version": "17.0.12", @@ -4403,11 +4395,11 @@ } }, "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", "dependencies": { - "@types/mime": "^1", + "@types/mime": "*", "@types/node": "*" } }, @@ -4723,14 +4715,14 @@ } }, "node_modules/algoliasearch-helper": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.8.2.tgz", - "integrity": "sha512-AXxiF0zT9oYwl8ZBgU/eRXvfYhz7cBA5YrLPlw9inZHdaYF0QEya/f1Zp1mPYMXc1v6VkHwBq4pk6/vayBLICg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.11.0.tgz", + "integrity": "sha512-TLl/MSjtQ98mgkd8hngWkzSjE+dAWldZ1NpJtv2mT+ZoFJ2P2zDE85oF9WafJOXWN9FbVRmyxpO5H+qXcNaFng==", "dependencies": { "@algolia/events": "^4.0.1" }, "peerDependencies": { - "algoliasearch": ">= 3.1 < 5" + "algoliasearch": ">= 3.1 < 6" } }, "node_modules/ansi-align": { @@ -4836,9 +4828,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", - "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "version": "10.4.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz", + "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==", "funding": [ { "type": "opencollective", @@ -4850,8 +4842,8 @@ } ], "dependencies": { - "browserslist": "^4.20.3", - "caniuse-lite": "^1.0.30001335", + "browserslist": "^4.21.3", + "caniuse-lite": "^1.0.30001373", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -4914,6 +4906,14 @@ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, "node_modules/babel-plugin-extract-import-names": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", @@ -4957,12 +4957,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz", - "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", + "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==", "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.0", + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.2", "semver": "^6.1.1" }, "peerDependencies": { @@ -4978,11 +4978,11 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", + "@babel/helper-define-polyfill-provider": "^0.3.2", "core-js-compat": "^3.21.0" }, "peerDependencies": { @@ -4990,11 +4990,11 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz", - "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz", + "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.0" + "@babel/helper-define-polyfill-provider": "^0.3.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -5022,7 +5022,7 @@ "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "node_modules/bcp-47-match": { "version": "1.0.3", @@ -5049,11 +5049,6 @@ "node": ">=8" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -5096,17 +5091,17 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/bonjour-service": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz", - "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz", + "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==", "dependencies": { "array-flatten": "^2.1.2", "dns-equal": "^1.0.0", "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.4" + "multicast-dns": "^7.2.5" } }, "node_modules/boolbase": { @@ -5156,9 +5151,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", - "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "funding": [ { "type": "opencollective", @@ -5170,11 +5165,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" }, "bin": { "browserslist": "cli.js" @@ -5303,9 +5297,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001350", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001350.tgz", - "integrity": "sha512-NZBql38Pzd+rAu5SPXv+qmTWGQuFsRiemHCJCAPvkoDxWV19/xqL2YHF32fDJ9SDLdLqfax8+S0CO3ncDCp9Iw==", + "version": "1.0.30001385", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001385.tgz", + "integrity": "sha512-MpiCqJGhBkHgpyimE9GWmZTnyHyEEM35u115bD3QBrXpjvL/JgcP8cUhKJshfmg4OtEHFenifcK5sZayEw5tvQ==", "funding": [ { "type": "opencollective", @@ -5369,9 +5363,9 @@ } }, "node_modules/cheerio": { - "version": "1.0.0-rc.11", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.11.tgz", - "integrity": "sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", @@ -5379,8 +5373,7 @@ "domutils": "^3.0.1", "htmlparser2": "^8.0.1", "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0", - "tslib": "^2.4.0" + "parse5-htmlparser2-tree-adapter": "^7.0.0" }, "engines": { "node": ">= 6" @@ -5664,9 +5657,9 @@ } }, "node_modules/clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", "engines": { "node": ">=6" } @@ -5705,14 +5698,14 @@ } }, "node_modules/colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" }, "node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" }, "node_modules/combine-promises": { "version": "1.1.0", @@ -5783,7 +5776,7 @@ "node_modules/compression/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/concat-map": { "version": "0.0.1", @@ -5807,9 +5800,9 @@ } }, "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "engines": { "node": ">=0.8" } @@ -5881,7 +5874,7 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/copy-text-to-clipboard": { "version": "3.0.1", @@ -5895,9 +5888,9 @@ } }, "node_modules/core-js": { - "version": "3.22.8", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", - "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5905,11 +5898,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.3.tgz", - "integrity": "sha512-wliMbvPI2idgFWpFe7UEyHMvu6HWgW8WA+HnDRtgzoSDYvXFMpoGX1H3tPDDXrcfUSyXafCLDd7hOeMQHEZxGw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz", + "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==", "dependencies": { - "browserslist": "^4.20.3", + "browserslist": "^4.21.3", "semver": "7.0.0" }, "funding": { @@ -5926,9 +5919,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.3.tgz", - "integrity": "sha512-oN88zz7nmKROMy8GOjs+LN+0LedIvbMdnB5XsTlhcOg1WGARt9l0LFg0zohdoFmCsEZ1h2ZbSQ6azj3M+vhzwQ==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5985,9 +5978,9 @@ } }, "node_modules/css-declaration-sorter": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", - "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==", "engines": { "node": "^10 || ^12 || >=14" }, @@ -6083,11 +6076,11 @@ } }, "node_modules/cssnano": { - "version": "5.1.11", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.11.tgz", - "integrity": "sha512-2nx+O6LvewPo5EBtYrKc8762mMkZRk9cMGIOP4UlkmxHm7ObxH+zvsJJ+qLwPkUc4/yumL/qJkavYi9NlodWIQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "dependencies": { - "cssnano-preset-default": "^5.2.11", + "cssnano-preset-default": "^5.2.12", "lilconfig": "^2.0.3", "yaml": "^1.10.2" }, @@ -6103,12 +6096,12 @@ } }, "node_modules/cssnano-preset-advanced": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.7.tgz", - "integrity": "sha512-VNOdTMRA60KhaURZhnkTGeluHQBHWDMwY7TIDu1Qydf88X6k8xZbV2I+Wlm8JRaj2oi18xvoIOAW17JneoZzEg==", + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.8.tgz", + "integrity": "sha512-xUlLLnEB1LjpEik+zgRNlk8Y/koBPPtONZjp7JKbXigeAmCrFvq9H0pXW5jJV45bQWAlmJ0sKy+IMr0XxLYQZg==", "dependencies": { "autoprefixer": "^10.3.7", - "cssnano-preset-default": "^5.2.11", + "cssnano-preset-default": "^5.2.12", "postcss-discard-unused": "^5.1.0", "postcss-merge-idents": "^5.1.1", "postcss-reduce-idents": "^5.2.0", @@ -6122,11 +6115,11 @@ } }, "node_modules/cssnano-preset-default": { - "version": "5.2.11", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.11.tgz", - "integrity": "sha512-4PadR1NtuaIK8MvLNuY7MznK4WJteldGlzCiMaaTiOUP+apeiIvUDIXykzUOoqgOOUAHrU64ncdD90NfZR3LSQ==", + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz", + "integrity": "sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==", "dependencies": { - "css-declaration-sorter": "^6.2.2", + "css-declaration-sorter": "^6.3.0", "cssnano-utils": "^3.1.0", "postcss-calc": "^8.2.3", "postcss-colormin": "^5.3.0", @@ -6135,7 +6128,7 @@ "postcss-discard-duplicates": "^5.1.0", "postcss-discard-empty": "^5.1.1", "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.5", + "postcss-merge-longhand": "^5.1.6", "postcss-merge-rules": "^5.1.2", "postcss-minify-font-values": "^5.1.0", "postcss-minify-gradients": "^5.1.1", @@ -6143,14 +6136,14 @@ "postcss-minify-selectors": "^5.2.1", "postcss-normalize-charset": "^5.1.0", "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.0", - "postcss-normalize-repeat-style": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", "postcss-normalize-string": "^5.1.0", "postcss-normalize-timing-functions": "^5.1.0", "postcss-normalize-unicode": "^5.1.0", "postcss-normalize-url": "^5.1.0", "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.2", + "postcss-ordered-values": "^5.1.3", "postcss-reduce-initial": "^5.1.0", "postcss-reduce-transforms": "^5.1.0", "postcss-svgo": "^5.1.0", @@ -6415,12 +6408,12 @@ "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" }, "node_modules/dns-packet": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", - "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -6592,12 +6585,12 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.124", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.124.tgz", - "integrity": "sha512-VhaE9VUYU6d2eIb+4xf83CATD+T+3bTzvxvlADkQE+c2hisiw3sZmvEDtsW704+Zky9WZGhBuQXijDVqSriQLA==" + "version": "1.4.234", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.234.tgz", + "integrity": "sha512-VqlJ4Ihd9F7eQIfwEtf7C0eZZDl6bQtpez8vx8VHN9iCZEzePZjr7n9OGFHSav4WN9zfLa2CFLowj0siBoc0hQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -6624,7 +6617,7 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -6778,7 +6771,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -6823,9 +6816,9 @@ } }, "node_modules/express": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.0.tgz", - "integrity": "sha512-EJEXxiTQJS3lIPrU1AE2vRuT7X7E+0KBbpm5GSoK524yl0K8X+er8zS2P14E64eqsVNoWbMCT7MpmQ+ErAhgRg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -6866,7 +6859,7 @@ "node_modules/express/node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/express/node_modules/debug": { "version": "2.6.9", @@ -6879,7 +6872,7 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/express/node_modules/safe-buffer": { "version": "5.2.1", @@ -7089,7 +7082,7 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/find-cache-dir": { "version": "3.3.2", @@ -7270,7 +7263,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -7893,7 +7886,7 @@ "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -8101,7 +8094,7 @@ "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" }, "node_modules/http-errors": { "version": "2.0.0", @@ -8119,9 +8112,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, "node_modules/http-proxy": { "version": "1.18.1", @@ -8276,9 +8269,9 @@ } }, "node_modules/infima": { - "version": "0.2.0-alpha.39", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.39.tgz", - "integrity": "sha512-UyYiwD3nwHakGhuOUfpe3baJ8gkiPpRVx4a4sE/Ag+932+Y6swtLsdPoRR8ezhwqGnduzxmFkjumV9roz6QoLw==", + "version": "0.2.0-alpha.42", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.42.tgz", + "integrity": "sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww==", "engines": { "node": ">=12" } @@ -8631,7 +8624,7 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/isexe": { "version": "2.0.0", @@ -8858,16 +8851,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, "node_modules/lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -8876,73 +8859,18 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -9102,17 +9030,17 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } }, "node_modules/memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", + "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", "dependencies": { - "fs-monkey": "1.0.3" + "fs-monkey": "^1.0.3" }, "engines": { "node": ">= 4.0.0" @@ -9121,7 +9049,7 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-stream": { "version": "2.0.0", @@ -9139,7 +9067,7 @@ "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -9216,9 +9144,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", - "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", + "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", "dependencies": { "schema-utils": "^4.0.0" }, @@ -9317,9 +9245,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz", - "integrity": "sha512-XkCYOU+rr2Ft3LI6w4ye51M3VK31qJXFIxu0XLw169PtKG0Zx47OrXeVW/GCYOfpC9s1yyyf1S+L8/4LY0J9Zw==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -9397,9 +9325,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, "node_modules/nopt": { "version": "1.0.10", @@ -9426,7 +9354,7 @@ "node_modules/normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "engines": { "node": ">=0.10.0" } @@ -9483,9 +9411,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9854,7 +9782,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -10099,9 +10027,9 @@ } }, "node_modules/postcss-merge-longhand": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.5.tgz", - "integrity": "sha512-NOG1grw9wIO+60arKa2YYsrbgvP6tp+jqc7+ZD5/MalIw234ooH2C6KlR6FEn4yle7GqZoBxSK1mLBE9KPur6w==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz", + "integrity": "sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==", "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^5.1.0" @@ -10271,9 +10199,9 @@ } }, "node_modules/postcss-normalize-positions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", - "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -10285,9 +10213,9 @@ } }, "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", - "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -10371,9 +10299,9 @@ } }, "node_modules/postcss-ordered-values": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.2.tgz", - "integrity": "sha512-wr2avRbW4HS2XE2ZCqpfp4N/tDC6GZKZ+SVP8UBTOVS8QWrc4TD8MYrebJrvVVlGPKszmiSCzue43NDiVtgDmg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", "dependencies": { "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" @@ -10534,17 +10462,17 @@ } }, "node_modules/prism-react-renderer": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.3.tgz", - "integrity": "sha512-Viur/7tBTCH2HmYzwCHmt2rEFn+rdIWNIINXyg0StiISbDiIhHKhrFuEK8eMkKgvsIYSjgGqy/hNyucHp6FpoQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", + "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", "peerDependencies": { "react": ">=0.14.9" } }, "node_modules/prismjs": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", - "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", "engines": { "node": ">=6" } @@ -11177,9 +11105,9 @@ } }, "node_modules/regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.0.1", @@ -11233,93 +11161,17 @@ "node_modules/regjsparser/node_modules/jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "bin": { "jsesc": "bin/jsesc" } }, - "node_modules/rehype-parse": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz", - "integrity": "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==", - "dependencies": { - "hast-util-from-parse5": "^5.0.0", - "parse5": "^5.0.0", - "xtend": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse/node_modules/hast-util-from-parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", - "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", - "dependencies": { - "ccount": "^1.0.3", - "hastscript": "^5.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.1.2", - "xtend": "^4.0.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse/node_modules/hastscript": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", - "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", - "dependencies": { - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse/node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remark-admonitions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz", - "integrity": "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==", - "dependencies": { - "rehype-parse": "^6.0.2", - "unified": "^8.4.2", - "unist-util-visit": "^2.0.1" - } - }, - "node_modules/remark-admonitions/node_modules/unified": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", - "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", - "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "engines": { + "node": ">= 0.10" } }, "node_modules/remark-emoji": { @@ -11497,7 +11349,7 @@ "node_modules/require-like": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", "engines": { "node": "*" } @@ -11505,7 +11357,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { "version": "1.20.0", @@ -11719,7 +11571,7 @@ "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "node_modules/selfsigned": { "version": "2.0.1", @@ -11799,7 +11651,7 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", @@ -11872,7 +11724,7 @@ "node_modules/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -11897,7 +11749,7 @@ "node_modules/serve-index/node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "engines": { "node": ">= 0.6" } @@ -11905,7 +11757,7 @@ "node_modules/serve-index/node_modules/http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -11919,12 +11771,12 @@ "node_modules/serve-index/node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", @@ -11934,7 +11786,7 @@ "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "engines": { "node": ">= 0.6" } @@ -11956,7 +11808,7 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -12099,11 +11951,6 @@ "node": ">= 6.3.0" } }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -12391,13 +12238,13 @@ } }, "node_modules/terser": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.0.tgz", - "integrity": "sha512-sgQ99P+fRBM1jAYzN9RTnD/xEWx/7LZgYTCRgmYriSq1wxxqiQPJgXkkLBBuwySDWJ2PP0PnVQyuf4xLUuH4Ng==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dependencies": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "bin": { @@ -12408,15 +12255,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "engines": { "node": ">= 10.13.0" @@ -12457,61 +12304,11 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/terser/node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/terser/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/terser/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "node_modules/terser/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12591,7 +12388,7 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/trim": { "version": "0.0.1", @@ -12896,11 +12693,36 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/update-notifier": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", @@ -13056,7 +12878,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -13077,7 +12899,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -13177,7 +12999,7 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { "version": "5.73.0", @@ -13256,12 +13078,12 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.1", + "memfs": "^3.4.3", "mime-types": "^2.1.31", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" @@ -13327,9 +13149,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz", - "integrity": "sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz", + "integrity": "sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw==", "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -13343,7 +13165,7 @@ "chokidar": "^3.5.3", "colorette": "^2.0.10", "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", + "connect-history-api-fallback": "^2.0.0", "default-gateway": "^6.0.3", "express": "^4.17.3", "graceful-fs": "^4.2.6", @@ -13367,6 +13189,10 @@ "engines": { "node": ">= 12.13.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, "peerDependencies": { "webpack": "^4.37.0 || ^5.0.0" }, @@ -13426,9 +13252,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", "engines": { "node": ">=10.0.0" }, @@ -13458,20 +13284,11 @@ } }, "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/events": { @@ -13499,14 +13316,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webpackbar": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", @@ -13548,7 +13357,7 @@ "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -13912,33 +13721,33 @@ } }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "requires": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==" + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==" }, "@babel/core": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", - "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "requires": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -13954,21 +13763,21 @@ } }, "@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "requires": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.18.13", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", - "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "requires": { - "@jridgewell/set-array": "^1.0.0", + "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } @@ -13976,29 +13785,29 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", - "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", - "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", "requires": { - "@babel/helper-explode-assignable-expression": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" } }, "@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" }, @@ -14011,37 +13820,35 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz", - "integrity": "sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-member-expression-to-functions": "^7.17.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz", - "integrity": "sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "regexpu-core": "^5.0.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", - "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz", + "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==", "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", @@ -14056,162 +13863,168 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==" + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" }, "@babel/helper-explode-assignable-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", - "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" } }, "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", - "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "requires": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.9" } }, "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-optimise-call-expression": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", - "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==" + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", - "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-wrap-function": "^7.16.8", - "@babel/types": "^7.16.8" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-replace-supers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", - "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-simple-access": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", - "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "requires": { - "@babel/types": "^7.18.2" + "@babel/types": "^7.18.6" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", - "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.9" } }, "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==" + }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" }, "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" }, "@babel/helper-wrap-function": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", - "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", "requires": { - "@babel/helper-function-name": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8" + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" } }, "@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -14245,17 +14058,17 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "supports-color": { "version": "5.5.0", @@ -14268,169 +14081,170 @@ } }, "@babel/parser": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", - "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==" + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.17.12.tgz", - "integrity": "sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz", - "integrity": "sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", + "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz", - "integrity": "sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", - "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz", - "integrity": "sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", - "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz", - "integrity": "sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz", - "integrity": "sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz", - "integrity": "sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz", - "integrity": "sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", - "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz", - "integrity": "sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.17.12" + "@babel/plugin-transform-parameters": "^7.18.8" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", - "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz", - "integrity": "sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz", - "integrity": "sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz", - "integrity": "sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-create-class-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz", - "integrity": "sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-syntax-async-generators": { @@ -14474,11 +14288,11 @@ } }, "@babel/plugin-syntax-import-assertions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz", - "integrity": "sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-syntax-json-strings": { @@ -14490,11 +14304,11 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz", - "integrity": "sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -14562,250 +14376,220 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", - "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz", - "integrity": "sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz", - "integrity": "sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-remap-async-to-generator": "^7.16.8" + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", - "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.17.12.tgz", - "integrity": "sha512-jw8XW/B1i7Lqwqj2CbrViPcZijSxfguBWZP2aN59NHgxUyO/OcO1mfdCxH13QhN5LbWhPkX+f+brKGhZTiqtZQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-classes": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.17.12.tgz", - "integrity": "sha512-cvO7lc7pZat6BsvH6l/EGaI8zpl8paICaoGk+7x7guvtfak/TbIf66nYmJOH13EuG0H+Xx3M+9LQDtSvZFKXKw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-optimise-call-expression": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-replace-supers": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz", - "integrity": "sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-destructuring": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz", - "integrity": "sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", - "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz", - "integrity": "sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", - "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-for-of": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz", - "integrity": "sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", - "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", "requires": { - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-literals": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz", - "integrity": "sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", - "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz", - "integrity": "sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", "requires": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz", - "integrity": "sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", "requires": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-simple-access": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.0.tgz", - "integrity": "sha512-vwKpxdHnlM5tIrRt/eA0bzfbi7gUBLN08vLu38np1nZevlPySRe6yvuATJB5F/WPJ+ur4OXwpVYq9+BsxqAQuQ==", - "requires": { - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-identifier": "^7.16.7", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - } } }, "@babel/plugin-transform-modules-umd": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz", - "integrity": "sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", "requires": { - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz", - "integrity": "sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.17.12", - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-new-target": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz", - "integrity": "sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-object-super": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", - "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-replace-supers": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" } }, "@babel/plugin-transform-parameters": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz", - "integrity": "sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-property-literals": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", - "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-react-constant-elements": { @@ -14817,69 +14601,69 @@ } }, "@babel/plugin-transform-react-display-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", - "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz", - "integrity": "sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz", + "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-jsx": "^7.17.12", - "@babel/types": "^7.17.12" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.10" } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", - "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", "requires": { - "@babel/plugin-transform-react-jsx": "^7.16.7" + "@babel/plugin-transform-react-jsx": "^7.18.6" } }, "@babel/plugin-transform-react-pure-annotations": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", - "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-regenerator": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz", - "integrity": "sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", + "@babel/helper-plugin-utils": "^7.18.6", "regenerator-transform": "^0.15.0" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz", - "integrity": "sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-runtime": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz", - "integrity": "sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==", - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.17.12", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", + "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", "semver": "^6.3.0" }, "dependencies": { @@ -14891,105 +14675,105 @@ } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", - "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-spread": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz", - "integrity": "sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", - "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-template-literals": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz", - "integrity": "sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz", - "integrity": "sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-typescript": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.4.tgz", - "integrity": "sha512-l4vHuSLUajptpHNEOUDEGsnpl9pfRLsN1XUoDQDD/YBuXTM+v37SHGS+c6n4jdcZy96QtuUuSvZYMLSSsjH8Mw==", + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz", + "integrity": "sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.0", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/plugin-syntax-typescript": "^7.17.12" + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-typescript": "^7.18.6" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", - "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", "requires": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", - "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/preset-env": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.2.tgz", - "integrity": "sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==", - "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.17.12", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-async-generator-functions": "^7.17.12", - "@babel/plugin-proposal-class-properties": "^7.17.12", - "@babel/plugin-proposal-class-static-block": "^7.18.0", - "@babel/plugin-proposal-dynamic-import": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.17.12", - "@babel/plugin-proposal-json-strings": "^7.17.12", - "@babel/plugin-proposal-logical-assignment-operators": "^7.17.12", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12", - "@babel/plugin-proposal-numeric-separator": "^7.16.7", - "@babel/plugin-proposal-object-rest-spread": "^7.18.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.17.12", - "@babel/plugin-proposal-private-methods": "^7.17.12", - "@babel/plugin-proposal-private-property-in-object": "^7.17.12", - "@babel/plugin-proposal-unicode-property-regex": "^7.17.12", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.17.12", + "@babel/plugin-syntax-import-assertions": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -14999,43 +14783,43 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.17.12", - "@babel/plugin-transform-async-to-generator": "^7.17.12", - "@babel/plugin-transform-block-scoped-functions": "^7.16.7", - "@babel/plugin-transform-block-scoping": "^7.17.12", - "@babel/plugin-transform-classes": "^7.17.12", - "@babel/plugin-transform-computed-properties": "^7.17.12", - "@babel/plugin-transform-destructuring": "^7.18.0", - "@babel/plugin-transform-dotall-regex": "^7.16.7", - "@babel/plugin-transform-duplicate-keys": "^7.17.12", - "@babel/plugin-transform-exponentiation-operator": "^7.16.7", - "@babel/plugin-transform-for-of": "^7.18.1", - "@babel/plugin-transform-function-name": "^7.16.7", - "@babel/plugin-transform-literals": "^7.17.12", - "@babel/plugin-transform-member-expression-literals": "^7.16.7", - "@babel/plugin-transform-modules-amd": "^7.18.0", - "@babel/plugin-transform-modules-commonjs": "^7.18.2", - "@babel/plugin-transform-modules-systemjs": "^7.18.0", - "@babel/plugin-transform-modules-umd": "^7.18.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.12", - "@babel/plugin-transform-new-target": "^7.17.12", - "@babel/plugin-transform-object-super": "^7.16.7", - "@babel/plugin-transform-parameters": "^7.17.12", - "@babel/plugin-transform-property-literals": "^7.16.7", - "@babel/plugin-transform-regenerator": "^7.18.0", - "@babel/plugin-transform-reserved-words": "^7.17.12", - "@babel/plugin-transform-shorthand-properties": "^7.16.7", - "@babel/plugin-transform-spread": "^7.17.12", - "@babel/plugin-transform-sticky-regex": "^7.16.7", - "@babel/plugin-transform-template-literals": "^7.18.2", - "@babel/plugin-transform-typeof-symbol": "^7.17.12", - "@babel/plugin-transform-unicode-escapes": "^7.16.7", - "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.2", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", "core-js-compat": "^3.22.1", "semver": "^6.3.0" }, @@ -15060,78 +14844,79 @@ } }, "@babel/preset-react": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.17.12.tgz", - "integrity": "sha512-h5U+rwreXtZaRBEQhW1hOJLMq8XNJBQ/9oymXiCXTuT/0uOwpbT0gUt+sXeOqoXBgNuUKI7TaObVwoEyWkpFgA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-react-display-name": "^7.16.7", - "@babel/plugin-transform-react-jsx": "^7.17.12", - "@babel/plugin-transform-react-jsx-development": "^7.16.7", - "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" } }, "@babel/preset-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.17.12.tgz", - "integrity": "sha512-S1ViF8W2QwAKUGJXxP9NAfNaqGDdEBJKpYkxHf5Yy2C4NPPzXGeR3Lhk7G8xJaaLcFTRfNjVbtbVtm8Gb0mqvg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", "requires": { - "@babel/helper-plugin-utils": "^7.17.12", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-typescript": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" } }, "@babel/runtime": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz", - "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz", - "integrity": "sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz", + "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==", "requires": { "core-js-pure": "^3.20.2", "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" } }, "@babel/traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", - "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.0", - "@babel/types": "^7.18.2", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } }, @@ -15157,58 +14942,67 @@ "optional": true }, "@docsearch/css": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.1.0.tgz", - "integrity": "sha512-bh5IskwkkodbvC0FzSg1AxMykfDl95hebEKwxNoq4e5QaGzOXSBgW8+jnMFZ7JU4sTBiB04vZWoUSzNrPboLZA==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.2.1.tgz", + "integrity": "sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==" }, "@docsearch/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.1.0.tgz", - "integrity": "sha512-bjB6ExnZzf++5B7Tfoi6UXgNwoUnNOfZ1NyvnvPhWgCMy5V/biAtLL4o7owmZSYdAKeFSvZ5Lxm0is4su/dBWg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.2.1.tgz", + "integrity": "sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==", "requires": { - "@algolia/autocomplete-core": "1.6.3", - "@docsearch/css": "3.1.0", + "@algolia/autocomplete-core": "1.7.1", + "@algolia/autocomplete-preset-algolia": "1.7.1", + "@docsearch/css": "3.2.1", "algoliasearch": "^4.0.0" }, "dependencies": { "@algolia/autocomplete-core": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.6.3.tgz", - "integrity": "sha512-dqQqRt01fX3YuVFrkceHsoCnzX0bLhrrg8itJI1NM68KjrPYQPYsE+kY8EZTCM4y8VDnhqJErR73xe/ZsV+qAA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.7.1.tgz", + "integrity": "sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==", "requires": { - "@algolia/autocomplete-shared": "1.6.3" + "@algolia/autocomplete-shared": "1.7.1" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.1.tgz", + "integrity": "sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==", + "requires": { + "@algolia/autocomplete-shared": "1.7.1" } }, "@algolia/autocomplete-shared": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.6.3.tgz", - "integrity": "sha512-UV46bnkTztyADFaETfzFC5ryIdGVb2zpAoYgu0tfcuYWjhg1KbLXveFffZIrGVoboqmAk1b+jMrl6iCja1i3lg==" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.1.tgz", + "integrity": "sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==" } } }, "@docusaurus/core": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.0-beta.21.tgz", - "integrity": "sha512-qysDMVp1M5UozK3u/qOxsEZsHF7jeBvJDS+5ItMPYmNKvMbNKeYZGA0g6S7F9hRDwjIlEbvo7BaX0UMDcmTAWA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.0.1.tgz", + "integrity": "sha512-Prd46TtZdiixlTl8a+h9bI5HegkfREjSNkrX2rVEwJZeziSz4ya+l7QDnbnCB2XbxEG8cveFo/F9q5lixolDtQ==", "requires": { - "@babel/core": "^7.18.2", - "@babel/generator": "^7.18.2", + "@babel/core": "^7.18.6", + "@babel/generator": "^7.18.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.18.2", - "@babel/preset-env": "^7.18.2", - "@babel/preset-react": "^7.17.12", - "@babel/preset-typescript": "^7.17.12", - "@babel/runtime": "^7.18.3", - "@babel/runtime-corejs3": "^7.18.3", - "@babel/traverse": "^7.18.2", - "@docusaurus/cssnano-preset": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", + "@babel/plugin-transform-runtime": "^7.18.6", + "@babel/preset-env": "^7.18.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@babel/runtime": "^7.18.6", + "@babel/runtime-corejs3": "^7.18.6", + "@babel/traverse": "^7.18.8", + "@docusaurus/cssnano-preset": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", - "@slorber/static-site-generator-webpack-plugin": "^4.0.4", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.2.1", "autoprefixer": "^10.4.7", "babel-loader": "^8.2.5", @@ -15221,10 +15015,10 @@ "combine-promises": "^1.1.0", "commander": "^5.1.0", "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.22.7", + "core-js": "^3.23.3", "css-loader": "^6.7.1", "css-minimizer-webpack-plugin": "^4.0.0", - "cssnano": "^5.1.9", + "cssnano": "^5.1.12", "del": "^6.1.1", "detect-port": "^1.3.0", "escape-html": "^1.0.3", @@ -15237,7 +15031,7 @@ "import-fresh": "^3.3.0", "leven": "^3.1.0", "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.6.0", + "mini-css-extract-plugin": "^2.6.1", "postcss": "^8.4.14", "postcss-loader": "^7.0.0", "prompts": "^2.4.2", @@ -15248,19 +15042,18 @@ "react-router": "^5.3.3", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.3", - "remark-admonitions": "^1.2.1", "rtl-detect": "^1.0.4", "semver": "^7.3.7", "serve-handler": "^6.1.3", "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.1", + "terser-webpack-plugin": "^5.3.3", "tslib": "^2.4.0", "update-notifier": "^5.1.0", "url-loader": "^4.1.1", "wait-on": "^6.0.1", - "webpack": "^5.72.1", + "webpack": "^5.73.0", "webpack-bundle-analyzer": "^4.5.0", - "webpack-dev-server": "^4.9.0", + "webpack-dev-server": "^4.9.3", "webpack-merge": "^5.8.0", "webpackbar": "^5.0.2" }, @@ -15294,14 +15087,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==" }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "requires": { - "object.assign": "^4.1.0" - } - }, "boxen": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", @@ -15457,34 +15242,34 @@ } }, "@docusaurus/cssnano-preset": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.21.tgz", - "integrity": "sha512-fhTZrg1vc6zYYZIIMXpe1TnEVGEjqscBo0s1uomSwKjjtMgu7wkzc1KKJYY7BndsSA+fVVkZ+OmL/kAsmK7xxw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.1.tgz", + "integrity": "sha512-MCJ6rRmlqLmlCsZIoIxOxDb0rYzIPEm9PYpsBW+CGNnbk+x8xK+11hnrxzvXHqDRNpxrq3Kq2jYUmg/DkqE6vg==", "requires": { - "cssnano-preset-advanced": "^5.3.5", + "cssnano-preset-advanced": "^5.3.8", "postcss": "^8.4.14", "postcss-sort-media-queries": "^4.2.1", "tslib": "^2.4.0" } }, "@docusaurus/logger": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.0-beta.21.tgz", - "integrity": "sha512-HTFp8FsSMrAj7Uxl5p72U+P7rjYU/LRRBazEoJbs9RaqoKEdtZuhv8MYPOCh46K9TekaoquRYqag2o23Qt4ggA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.0.1.tgz", + "integrity": "sha512-wIWseCKko1w/WARcDjO3N/XoJ0q/VE42AthP0eNAfEazDjJ94NXbaI6wuUsuY/bMg6hTKGVIpphjj2LoX3g6dA==", "requires": { "chalk": "^4.1.2", "tslib": "^2.4.0" } }, "@docusaurus/mdx-loader": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.21.tgz", - "integrity": "sha512-AI+4obJnpOaBOAYV6df2ux5Y1YJCBS+MhXFf0yhED12sVLJi2vffZgdamYd/d/FwvWDw6QLs/VD2jebd7P50yQ==", - "requires": { - "@babel/parser": "^7.18.3", - "@babel/traverse": "^7.18.2", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.0.1.tgz", + "integrity": "sha512-tdNeljdilXCmhbaEND3SAgsqaw/oh7v9onT5yrIrL26OSk2AFwd+MIi4R8jt8vq33M0R4rz2wpknm0fQIkDdvQ==", + "requires": { + "@babel/parser": "^7.18.8", + "@babel/traverse": "^7.18.8", + "@docusaurus/logger": "2.0.1", + "@docusaurus/utils": "2.0.1", "@mdx-js/mdx": "^1.6.22", "escape-html": "^1.0.3", "file-loader": "^6.2.0", @@ -15494,145 +15279,182 @@ "remark-emoji": "^2.2.0", "stringify-object": "^3.3.0", "tslib": "^2.4.0", + "unified": "^9.2.2", "unist-util-visit": "^2.0.3", "url-loader": "^4.1.1", - "webpack": "^5.72.1" + "webpack": "^5.73.0" + }, + "dependencies": { + "unified": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", + "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + } } }, "@docusaurus/module-type-aliases": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.0-beta.21.tgz", - "integrity": "sha512-gRkWICgQZiqSJgrwRKWjXm5gAB+9IcfYdUbCG0PRPP/G8sNs9zBIOY4uT4Z5ox2CWFEm44U3RTTxj7BiLVMBXw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.0.1.tgz", + "integrity": "sha512-f888ylnxHAM/3T8p1lx08+lTc6/g7AweSRfRuZvrVhHXj3Tz/nTTxaP6gPTGkJK7WLqTagpar/IGP6/74IBbkg==", "requires": { - "@docusaurus/types": "2.0.0-beta.21", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/types": "2.0.1", + "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", "@types/react-router-dom": "*", - "react-helmet-async": "*" + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" + }, + "dependencies": { + "react-loadable": { + "version": "npm:@docusaurus/react-loadable@5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "requires": { + "@types/react": "*", + "prop-types": "^15.6.2" + } + } } }, "@docusaurus/plugin-content-blog": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.21.tgz", - "integrity": "sha512-IP21yJViP3oBmgsWBU5LhrG1MZXV4mYCQSoCAboimESmy1Z11RCNP2tXaqizE3iTmXOwZZL+SNBk06ajKCEzWg==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", - "cheerio": "^1.0.0-rc.11", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.1.tgz", + "integrity": "sha512-/4ua3iFYcpwgpeYgHnhVGROB/ybnauLH2+rICb4vz/+Gn1hjAmGXVYq1fk8g49zGs3uxx5nc0H5bL9P0g977IQ==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^10.1.0", "lodash": "^4.17.21", "reading-time": "^1.5.0", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", "unist-util-visit": "^2.0.3", "utility-types": "^3.10.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" } }, "@docusaurus/plugin-content-docs": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.21.tgz", - "integrity": "sha512-aa4vrzJy4xRy81wNskyhE3wzRf3AgcESZ1nfKh8xgHUkT7fDTZ1UWlg50Jb3LBCQFFyQG2XQB9N6llskI/KUnw==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.1.tgz", + "integrity": "sha512-2qeBWRy1EjgnXdwAO6/csDIS1UVNmhmtk/bQ2s9jqjpwM8YVgZ8QVdkxFAMWXgZWDQdwWwdP1rnmoEelE4HknQ==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", + "@types/react-router-config": "^5.0.6", "combine-promises": "^1.1.0", "fs-extra": "^10.1.0", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", "utility-types": "^3.10.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" } }, "@docusaurus/plugin-content-pages": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.21.tgz", - "integrity": "sha512-DmXOXjqNI+7X5hISzCvt54QIK6XBugu2MOxjxzuqI7q92Lk/EVdraEj5mthlH8IaEH/VlpWYJ1O9TzLqX5vH2g==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/mdx-loader": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.1.tgz", + "integrity": "sha512-6apSVeJENnNecAH5cm5VnRqR103M6qSI6IuiP7tVfD5H4AWrfDNkvJQV2+R2PIq3bGrwmX4fcXl1x4g0oo7iwA==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "fs-extra": "^10.1.0", - "remark-admonitions": "^1.2.1", "tslib": "^2.4.0", - "webpack": "^5.72.1" + "webpack": "^5.73.0" } }, "@docusaurus/plugin-debug": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.21.tgz", - "integrity": "sha512-P54J4q4ecsyWW0Jy4zbimSIHna999AfbxpXGmF1IjyHrjoA3PtuakV1Ai51XrGEAaIq9q6qMQkEhbUd3CffGAw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.0.1.tgz", + "integrity": "sha512-jpZBT5HK7SWx1LRQyv9d14i44vSsKXGZsSPA2ndth5HykHJsiAj9Fwl1AtzmtGYuBmI+iXQyOd4MAMHd4ZZ1tg==", "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", "fs-extra": "^10.1.0", "react-json-view": "^1.21.3", "tslib": "^2.4.0" } }, "@docusaurus/plugin-google-analytics": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.21.tgz", - "integrity": "sha512-+5MS0PeGaJRgPuNZlbd/WMdQSpOACaxEz7A81HAxm6kE+tIASTW3l8jgj1eWFy/PGPzaLnQrEjxI1McAfnYmQw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.1.tgz", + "integrity": "sha512-d5qb+ZeQcg1Czoxc+RacETjLdp2sN/TAd7PGN/GrvtijCdgNmvVAtZ9QgajBTG0YbJFVPTeZ39ad2bpoOexX0w==", "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" } }, "@docusaurus/plugin-google-gtag": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.21.tgz", - "integrity": "sha512-4zxKZOnf0rfh6myXLG7a6YZfQcxYDMBsWqANEjCX77H5gPdK+GHZuDrxK6sjFvRBv4liYCrNjo7HJ4DpPoT0zA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.1.tgz", + "integrity": "sha512-qiRufJe2FvIyzICbkjm4VbVCI1hyEju/CebfDKkKh2ZtV4q6DM1WZG7D6VoQSXL8MrMFB895gipOM4BwdM8VsQ==", "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "@docusaurus/core": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" } }, "@docusaurus/plugin-sitemap": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.21.tgz", - "integrity": "sha512-/ynWbcXZXcYZ6sT2X6vAJbnfqcPxwdGEybd0rcRZi4gBHq6adMofYI25AqELmnbBDxt0If+vlAeUHFRG5ueP7Q==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.1.tgz", + "integrity": "sha512-KcYuIUIp2JPzUf+Xa7W2BSsjLgN1/0h+VAz7D/C3RYjAgC5ApPX8wO+TECmGfunl/m7WKGUmLabfOon/as64kQ==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "fs-extra": "^10.1.0", "sitemap": "^7.1.1", "tslib": "^2.4.0" } }, "@docusaurus/preset-classic": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.21.tgz", - "integrity": "sha512-KvBnIUu7y69pNTJ9UhX6SdNlK6prR//J3L4rhN897tb8xx04xHHILlPXko2Il+C3Xzgh3OCgyvkoz9K6YlFTDw==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "@docusaurus/plugin-debug": "2.0.0-beta.21", - "@docusaurus/plugin-google-analytics": "2.0.0-beta.21", - "@docusaurus/plugin-google-gtag": "2.0.0-beta.21", - "@docusaurus/plugin-sitemap": "2.0.0-beta.21", - "@docusaurus/theme-classic": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-search-algolia": "2.0.0-beta.21" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.0.1.tgz", + "integrity": "sha512-nOoniTg46My1qdDlLWeFs55uEmxOJ+9WMF8KKG8KMCu5LAvpemMi7rQd4x8Tw+xiPHZ/sQzH9JmPTMPRE4QGPw==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/plugin-debug": "2.0.1", + "@docusaurus/plugin-google-analytics": "2.0.1", + "@docusaurus/plugin-google-gtag": "2.0.1", + "@docusaurus/plugin-sitemap": "2.0.1", + "@docusaurus/theme-classic": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-search-algolia": "2.0.1", + "@docusaurus/types": "2.0.1" } }, "@docusaurus/react-loadable": { @@ -15645,65 +15467,74 @@ } }, "@docusaurus/theme-classic": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.21.tgz", - "integrity": "sha512-Ge0WNdTefD0VDQfaIMRRWa8tWMG9+8/OlBRd5MK88/TZfqdBq7b/gnCSaalQlvZwwkj6notkKhHx72+MKwWUJA==", - "requires": { - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-translations": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-common": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.0.1.tgz", + "integrity": "sha512-0jfigiqkUwIuKOw7Me5tqUM9BBvoQX7qqeevx7v4tkYQexPhk3VYSZo7aRuoJ9oyW5makCTPX551PMJzmq7+sw==", + "requires": { + "@docusaurus/core": "2.0.1", + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-translations": "2.0.1", + "@docusaurus/types": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-common": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "@mdx-js/react": "^1.6.22", - "clsx": "^1.1.1", + "clsx": "^1.2.1", "copy-text-to-clipboard": "^3.0.1", - "infima": "0.2.0-alpha.39", + "infima": "0.2.0-alpha.42", "lodash": "^4.17.21", "nprogress": "^0.2.0", "postcss": "^8.4.14", - "prism-react-renderer": "^1.3.3", + "prism-react-renderer": "^1.3.5", "prismjs": "^1.28.0", "react-router-dom": "^5.3.3", "rtlcss": "^3.5.0", - "tslib": "^2.4.0" + "tslib": "^2.4.0", + "utility-types": "^3.10.0" } }, "@docusaurus/theme-common": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.0-beta.21.tgz", - "integrity": "sha512-fTKoTLRfjuFG6c3iwnVjIIOensxWMgdBKLfyE5iih3Lq7tQgkE7NyTGG9BKLrnTJ7cAD2UXdXM9xbB7tBf1qzg==", - "requires": { - "@docusaurus/module-type-aliases": "2.0.0-beta.21", - "@docusaurus/plugin-content-blog": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/plugin-content-pages": "2.0.0-beta.21", - "clsx": "^1.1.1", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.0.1.tgz", + "integrity": "sha512-I3b6e/ryiTQMsbES40cP0DRGnfr0E2qghVq+XecyMKjBPejISoSFEDn0MsnbW8Q26k1Dh/0qDH8QKDqaZZgLhA==", + "requires": { + "@docusaurus/mdx-loader": "2.0.1", + "@docusaurus/module-type-aliases": "2.0.1", + "@docusaurus/plugin-content-blog": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/plugin-content-pages": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^1.2.1", "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^1.3.3", + "prism-react-renderer": "^1.3.5", "tslib": "^2.4.0", "utility-types": "^3.10.0" } }, "@docusaurus/theme-search-algolia": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.21.tgz", - "integrity": "sha512-T1jKT8MVSSfnztSqeebUOpWHPoHKtwDXtKYE0xC99JWoZ+mMfv8AFhVSoSddn54jLJjV36mxg841eHQIySMCpQ==", - "requires": { - "@docsearch/react": "^3.1.0", - "@docusaurus/core": "2.0.0-beta.21", - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/plugin-content-docs": "2.0.0-beta.21", - "@docusaurus/theme-common": "2.0.0-beta.21", - "@docusaurus/theme-translations": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", - "@docusaurus/utils-validation": "2.0.0-beta.21", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.1.tgz", + "integrity": "sha512-cw3NaOSKbYlsY6uNj4PgO+5mwyQ3aEWre5RlmvjStaz2cbD15Nr69VG8Rd/F6Q5VsCT8BvSdkPDdDG5d/ACexg==", + "requires": { + "@docsearch/react": "^3.1.1", + "@docusaurus/core": "2.0.1", + "@docusaurus/logger": "2.0.1", + "@docusaurus/plugin-content-docs": "2.0.1", + "@docusaurus/theme-common": "2.0.1", + "@docusaurus/theme-translations": "2.0.1", + "@docusaurus/utils": "2.0.1", + "@docusaurus/utils-validation": "2.0.1", "algoliasearch": "^4.13.1", - "algoliasearch-helper": "^3.8.2", - "clsx": "^1.1.1", + "algoliasearch-helper": "^3.10.0", + "clsx": "^1.2.1", "eta": "^1.12.3", "fs-extra": "^10.1.0", "lodash": "^4.17.21", @@ -15712,34 +15543,35 @@ } }, "@docusaurus/theme-translations": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.21.tgz", - "integrity": "sha512-dLVT9OIIBs6MpzMb1bAy+C0DPJK3e3DNctG+ES0EP45gzEqQxzs4IsghpT+QDaOsuhNnAlosgJpFWX3rqxF9xA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.0.1.tgz", + "integrity": "sha512-v1MYYlbsdX+rtKnXFcIAn9ar0Z6K0yjqnCYS0p/KLCLrfJwfJ8A3oRJw2HiaIb8jQfk1WMY2h5Qi1p4vHOekQw==", "requires": { "fs-extra": "^10.1.0", "tslib": "^2.4.0" } }, "@docusaurus/types": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.0-beta.21.tgz", - "integrity": "sha512-/GH6Npmq81eQfMC/ikS00QSv9jNyO1RXEpNSx5GLA3sFX8Iib26g2YI2zqNplM8nyxzZ2jVBuvUoeODTIbTchQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.0.1.tgz", + "integrity": "sha512-o+4hAFWkj3sBszVnRTAnNqtAIuIW0bNaYyDwQhQ6bdz3RAPEq9cDKZxMpajsj4z2nRty8XjzhyufAAjxFTyrfg==", "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", "commander": "^5.1.0", - "history": "^4.9.0", "joi": "^17.6.0", "react-helmet-async": "^1.3.0", "utility-types": "^3.10.0", - "webpack": "^5.72.1", + "webpack": "^5.73.0", "webpack-merge": "^5.8.0" } }, "@docusaurus/utils": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.0-beta.21.tgz", - "integrity": "sha512-M/BrVCDmmUPZLxtiStBgzpQ4I5hqkggcpnQmEN+LbvbohjbtVnnnZQ0vptIziv1w8jry/woY+ePsyOO7O/yeLQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.0.1.tgz", + "integrity": "sha512-u2Vdl/eoVwMfUjDCkg7FjxoiwFs/XhVVtNxQEw8cvB+qaw6QWyT73m96VZzWtUb1fDOefHoZ+bZ0ObFeKk9lMQ==", "requires": { - "@docusaurus/logger": "2.0.0-beta.21", + "@docusaurus/logger": "2.0.1", "@svgr/webpack": "^6.2.1", "file-loader": "^6.2.0", "fs-extra": "^10.1.0", @@ -15753,24 +15585,24 @@ "shelljs": "^0.8.5", "tslib": "^2.4.0", "url-loader": "^4.1.1", - "webpack": "^5.72.1" + "webpack": "^5.73.0" } }, "@docusaurus/utils-common": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.0-beta.21.tgz", - "integrity": "sha512-5w+6KQuJb6pUR2M8xyVuTMvO5NFQm/p8TOTDFTx60wt3p0P1rRX00v6FYsD4PK6pgmuoKjt2+Ls8dtSXc4qFpQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.0.1.tgz", + "integrity": "sha512-kajCCDCXRd1HFH5EUW31MPaQcsyNlGakpkDoTBtBvpa4EIPvWaSKy7TIqYKHrZjX4tnJ0YbEJvaXfjjgdq5xSg==", "requires": { "tslib": "^2.4.0" } }, "@docusaurus/utils-validation": { - "version": "2.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.21.tgz", - "integrity": "sha512-6NG1FHTRjv1MFzqW//292z7uCs77vntpWEbZBHk3n67aB1HoMn5SOwjLPtRDjbCgn6HCHFmdiJr6euCbjhYolg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.0.1.tgz", + "integrity": "sha512-f14AnwFBy4/1A19zWthK+Ii80YDz+4qt8oPpK3julywXsheSxPBqgsND3LVBBvB2p3rJHvbo2m3HyB9Tco1JRw==", "requires": { - "@docusaurus/logger": "2.0.0-beta.21", - "@docusaurus/utils": "2.0.0-beta.21", + "@docusaurus/logger": "2.0.1", + "@docusaurus/utils": "2.0.1", "joi": "^17.6.0", "js-yaml": "^4.1.0", "tslib": "^2.4.0" @@ -15947,24 +15779,45 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==" }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, "@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "@leichtgewicht/ip-codec": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", - "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "@mdx-js/mdx": { "version": "1.6.22", @@ -16336,112 +16189,13 @@ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" }, "@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.4.tgz", - "integrity": "sha512-FvMavoWEIePps6/JwGCOLYKCRhuwIHhMtmbKpBFgzNkxwpa/569LfTkrbRk1m1I3n+ezJK4on9E1A6cjuZmD9g==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", + "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", "requires": { - "bluebird": "^3.7.1", - "cheerio": "^0.22.0", "eval": "^0.1.8", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - } + "p-map": "^4.0.0", + "webpack-sources": "^3.2.2" } }, "@svgr/babel-plugin-add-jsx-attribute": { @@ -16644,9 +16398,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -16672,9 +16426,9 @@ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" }, "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", "requires": { "@types/node": "*" } @@ -16698,9 +16452,9 @@ } }, "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, "@types/node": { "version": "17.0.12", @@ -16814,11 +16568,11 @@ } }, "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", "requires": { - "@types/mime": "^1", + "@types/mime": "*", "@types/node": "*" } }, @@ -17098,9 +16852,9 @@ } }, "algoliasearch-helper": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.8.2.tgz", - "integrity": "sha512-AXxiF0zT9oYwl8ZBgU/eRXvfYhz7cBA5YrLPlw9inZHdaYF0QEya/f1Zp1mPYMXc1v6VkHwBq4pk6/vayBLICg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.11.0.tgz", + "integrity": "sha512-TLl/MSjtQ98mgkd8hngWkzSjE+dAWldZ1NpJtv2mT+ZoFJ2P2zDE85oF9WafJOXWN9FbVRmyxpO5H+qXcNaFng==", "requires": { "@algolia/events": "^4.0.1" } @@ -17184,12 +16938,12 @@ } }, "autoprefixer": { - "version": "10.4.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", - "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "version": "10.4.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz", + "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==", "requires": { - "browserslist": "^4.20.3", - "caniuse-lite": "^1.0.30001335", + "browserslist": "^4.21.3", + "caniuse-lite": "^1.0.30001373", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -17231,6 +16985,14 @@ } } }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, "babel-plugin-extract-import-names": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", @@ -17271,12 +17033,12 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz", - "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", + "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==", "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.3.0", + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.2", "semver": "^6.1.1" }, "dependencies": { @@ -17288,20 +17050,20 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1", + "@babel/helper-define-polyfill-provider": "^0.3.2", "core-js-compat": "^3.21.0" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz", - "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz", + "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==", "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.0" + "@babel/helper-define-polyfill-provider": "^0.3.2" } }, "bail": { @@ -17322,7 +17084,7 @@ "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "bcp-47-match": { "version": "1.0.3", @@ -17339,11 +17101,6 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -17379,19 +17136,19 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, "bonjour-service": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz", - "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz", + "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==", "requires": { "array-flatten": "^2.1.2", "dns-equal": "^1.0.0", "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.4" + "multicast-dns": "^7.2.5" } }, "boolbase": { @@ -17432,15 +17189,14 @@ } }, "browserslist": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", - "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "requires": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" } }, "buffer-from": { @@ -17532,9 +17288,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001350", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001350.tgz", - "integrity": "sha512-NZBql38Pzd+rAu5SPXv+qmTWGQuFsRiemHCJCAPvkoDxWV19/xqL2YHF32fDJ9SDLdLqfax8+S0CO3ncDCp9Iw==" + "version": "1.0.30001385", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001385.tgz", + "integrity": "sha512-MpiCqJGhBkHgpyimE9GWmZTnyHyEEM35u115bD3QBrXpjvL/JgcP8cUhKJshfmg4OtEHFenifcK5sZayEw5tvQ==" }, "ccount": { "version": "1.1.0", @@ -17566,9 +17322,9 @@ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" }, "cheerio": { - "version": "1.0.0-rc.11", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.11.tgz", - "integrity": "sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "requires": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", @@ -17576,8 +17332,7 @@ "domutils": "^3.0.1", "htmlparser2": "^8.0.1", "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0", - "tslib": "^2.4.0" + "parse5-htmlparser2-tree-adapter": "^7.0.0" }, "dependencies": { "dom-serializer": { @@ -17772,9 +17527,9 @@ } }, "clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" }, "collapse-white-space": { "version": "1.0.6", @@ -17800,14 +17555,14 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colord": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", - "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" }, "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" }, "combine-promises": { "version": "1.1.0", @@ -17862,7 +17617,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -17885,9 +17640,9 @@ } }, "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" }, "consola": { "version": "2.15.3", @@ -17935,7 +17690,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "copy-text-to-clipboard": { "version": "3.0.1", @@ -17943,16 +17698,16 @@ "integrity": "sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q==" }, "core-js": { - "version": "3.22.8", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", - "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" }, "core-js-compat": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.3.tgz", - "integrity": "sha512-wliMbvPI2idgFWpFe7UEyHMvu6HWgW8WA+HnDRtgzoSDYvXFMpoGX1H3tPDDXrcfUSyXafCLDd7hOeMQHEZxGw==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz", + "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==", "requires": { - "browserslist": "^4.20.3", + "browserslist": "^4.21.3", "semver": "7.0.0" }, "dependencies": { @@ -17964,9 +17719,9 @@ } }, "core-js-pure": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.3.tgz", - "integrity": "sha512-oN88zz7nmKROMy8GOjs+LN+0LedIvbMdnB5XsTlhcOg1WGARt9l0LFg0zohdoFmCsEZ1h2ZbSQ6azj3M+vhzwQ==" + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==" }, "core-util-is": { "version": "1.0.3", @@ -18009,9 +17764,9 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" }, "css-declaration-sorter": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", - "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==", "requires": {} }, "css-loader": { @@ -18073,22 +17828,22 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssnano": { - "version": "5.1.11", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.11.tgz", - "integrity": "sha512-2nx+O6LvewPo5EBtYrKc8762mMkZRk9cMGIOP4UlkmxHm7ObxH+zvsJJ+qLwPkUc4/yumL/qJkavYi9NlodWIQ==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", "requires": { - "cssnano-preset-default": "^5.2.11", + "cssnano-preset-default": "^5.2.12", "lilconfig": "^2.0.3", "yaml": "^1.10.2" } }, "cssnano-preset-advanced": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.7.tgz", - "integrity": "sha512-VNOdTMRA60KhaURZhnkTGeluHQBHWDMwY7TIDu1Qydf88X6k8xZbV2I+Wlm8JRaj2oi18xvoIOAW17JneoZzEg==", + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.8.tgz", + "integrity": "sha512-xUlLLnEB1LjpEik+zgRNlk8Y/koBPPtONZjp7JKbXigeAmCrFvq9H0pXW5jJV45bQWAlmJ0sKy+IMr0XxLYQZg==", "requires": { "autoprefixer": "^10.3.7", - "cssnano-preset-default": "^5.2.11", + "cssnano-preset-default": "^5.2.12", "postcss-discard-unused": "^5.1.0", "postcss-merge-idents": "^5.1.1", "postcss-reduce-idents": "^5.2.0", @@ -18096,11 +17851,11 @@ } }, "cssnano-preset-default": { - "version": "5.2.11", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.11.tgz", - "integrity": "sha512-4PadR1NtuaIK8MvLNuY7MznK4WJteldGlzCiMaaTiOUP+apeiIvUDIXykzUOoqgOOUAHrU64ncdD90NfZR3LSQ==", + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz", + "integrity": "sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==", "requires": { - "css-declaration-sorter": "^6.2.2", + "css-declaration-sorter": "^6.3.0", "cssnano-utils": "^3.1.0", "postcss-calc": "^8.2.3", "postcss-colormin": "^5.3.0", @@ -18109,7 +17864,7 @@ "postcss-discard-duplicates": "^5.1.0", "postcss-discard-empty": "^5.1.1", "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.5", + "postcss-merge-longhand": "^5.1.6", "postcss-merge-rules": "^5.1.2", "postcss-minify-font-values": "^5.1.0", "postcss-minify-gradients": "^5.1.1", @@ -18117,14 +17872,14 @@ "postcss-minify-selectors": "^5.2.1", "postcss-normalize-charset": "^5.1.0", "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.0", - "postcss-normalize-repeat-style": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", "postcss-normalize-string": "^5.1.0", "postcss-normalize-timing-functions": "^5.1.0", "postcss-normalize-unicode": "^5.1.0", "postcss-normalize-url": "^5.1.0", "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.2", + "postcss-ordered-values": "^5.1.3", "postcss-reduce-initial": "^5.1.0", "postcss-reduce-transforms": "^5.1.0", "postcss-svgo": "^5.1.0", @@ -18309,12 +18064,12 @@ "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" }, "dns-packet": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz", - "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", "requires": { "@leichtgewicht/ip-codec": "^2.0.1" } @@ -18450,12 +18205,12 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.124", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.124.tgz", - "integrity": "sha512-VhaE9VUYU6d2eIb+4xf83CATD+T+3bTzvxvlADkQE+c2hisiw3sZmvEDtsW704+Zky9WZGhBuQXijDVqSriQLA==" + "version": "1.4.234", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.234.tgz", + "integrity": "sha512-VqlJ4Ihd9F7eQIfwEtf7C0eZZDl6bQtpez8vx8VHN9iCZEzePZjr7n9OGFHSav4WN9zfLa2CFLowj0siBoc0hQ==" }, "emoji-regex": { "version": "9.2.2", @@ -18475,7 +18230,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -18579,7 +18334,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "eval": { "version": "0.1.8", @@ -18612,9 +18367,9 @@ } }, "express": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.0.tgz", - "integrity": "sha512-EJEXxiTQJS3lIPrU1AE2vRuT7X7E+0KBbpm5GSoK524yl0K8X+er8zS2P14E64eqsVNoWbMCT7MpmQ+ErAhgRg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -18652,7 +18407,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "debug": { "version": "2.6.9", @@ -18665,7 +18420,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "safe-buffer": { "version": "5.2.1", @@ -18827,7 +18582,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -18942,7 +18697,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-extra": { "version": "10.1.0", @@ -19410,7 +19165,7 @@ "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "requires": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -19567,7 +19322,7 @@ "http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" }, "http-errors": { "version": "2.0.0", @@ -19582,9 +19337,9 @@ } }, "http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==" + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, "http-proxy": { "version": "1.18.1", @@ -19682,9 +19437,9 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, "infima": { - "version": "0.2.0-alpha.39", - "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.39.tgz", - "integrity": "sha512-UyYiwD3nwHakGhuOUfpe3baJ8gkiPpRVx4a4sE/Ag+932+Y6swtLsdPoRR8ezhwqGnduzxmFkjumV9roz6QoLw==" + "version": "0.2.0-alpha.42", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.42.tgz", + "integrity": "sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww==" }, "inflight": { "version": "1.0.6", @@ -19914,7 +19669,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "isexe": { "version": "2.0.0", @@ -20087,16 +19842,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" - }, "lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -20105,73 +19850,18 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==" }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" - }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -20295,20 +19985,20 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", + "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", "requires": { - "fs-monkey": "1.0.3" + "fs-monkey": "^1.0.3" } }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-stream": { "version": "2.0.0", @@ -20323,7 +20013,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "4.0.5", @@ -20372,9 +20062,9 @@ } }, "mini-css-extract-plugin": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", - "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", + "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", "requires": { "schema-utils": "^4.0.0" }, @@ -20445,9 +20135,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.4.tgz", - "integrity": "sha512-XkCYOU+rr2Ft3LI6w4ye51M3VK31qJXFIxu0XLw169PtKG0Zx47OrXeVW/GCYOfpC9s1yyyf1S+L8/4LY0J9Zw==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "requires": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -20499,9 +20189,9 @@ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" }, "node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, "nopt": { "version": "1.0.10", @@ -20519,7 +20209,7 @@ "normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" }, "normalize-url": { "version": "6.1.0", @@ -20558,9 +20248,9 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" }, "object-keys": { "version": "1.1.1", @@ -20823,7 +20513,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "path-type": { "version": "4.0.0", @@ -20977,9 +20667,9 @@ } }, "postcss-merge-longhand": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.5.tgz", - "integrity": "sha512-NOG1grw9wIO+60arKa2YYsrbgvP6tp+jqc7+ZD5/MalIw234ooH2C6KlR6FEn4yle7GqZoBxSK1mLBE9KPur6w==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz", + "integrity": "sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==", "requires": { "postcss-value-parser": "^4.2.0", "stylehacks": "^5.1.0" @@ -21079,17 +20769,17 @@ } }, "postcss-normalize-positions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz", - "integrity": "sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", "requires": { "postcss-value-parser": "^4.2.0" } }, "postcss-normalize-repeat-style": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz", - "integrity": "sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", "requires": { "postcss-value-parser": "^4.2.0" } @@ -21137,9 +20827,9 @@ } }, "postcss-ordered-values": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.2.tgz", - "integrity": "sha512-wr2avRbW4HS2XE2ZCqpfp4N/tDC6GZKZ+SVP8UBTOVS8QWrc4TD8MYrebJrvVVlGPKszmiSCzue43NDiVtgDmg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", "requires": { "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" @@ -21240,15 +20930,15 @@ "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" }, "prism-react-renderer": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.3.tgz", - "integrity": "sha512-Viur/7tBTCH2HmYzwCHmt2rEFn+rdIWNIINXyg0StiISbDiIhHKhrFuEK8eMkKgvsIYSjgGqy/hNyucHp6FpoQ==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", + "integrity": "sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==", "requires": {} }, "prismjs": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", - "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" }, "process-nextick-args": { "version": "2.0.1", @@ -21743,9 +21433,9 @@ } }, "regexpu-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", - "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", "requires": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.0.1", @@ -21787,47 +21477,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - } - } - }, - "rehype-parse": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.2.tgz", - "integrity": "sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug==", - "requires": { - "hast-util-from-parse5": "^5.0.0", - "parse5": "^5.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "hast-util-from-parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz", - "integrity": "sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA==", - "requires": { - "ccount": "^1.0.3", - "hastscript": "^5.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.1.2", - "xtend": "^4.0.1" - } - }, - "hastscript": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", - "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", - "requires": { - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" } } }, @@ -21836,30 +21486,6 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, - "remark-admonitions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/remark-admonitions/-/remark-admonitions-1.2.1.tgz", - "integrity": "sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow==", - "requires": { - "rehype-parse": "^6.0.2", - "unified": "^8.4.2", - "unist-util-visit": "^2.0.1" - }, - "dependencies": { - "unified": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz", - "integrity": "sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA==", - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" - } - } - } - }, "remark-emoji": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-2.2.0.tgz", @@ -21999,12 +21625,12 @@ "require-like": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=" + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==" }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "resolve": { "version": "1.20.0", @@ -22156,7 +21782,7 @@ "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" }, "selfsigned": { "version": "2.0.1", @@ -22220,7 +21846,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -22287,7 +21913,7 @@ "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "requires": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -22309,12 +21935,12 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -22325,12 +21951,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "setprototypeof": { "version": "1.1.0", @@ -22340,7 +21966,7 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" } } }, @@ -22358,7 +21984,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "setprototypeof": { "version": "1.2.0", @@ -22467,11 +22093,6 @@ "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz", "integrity": "sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw==" }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -22688,13 +22309,13 @@ "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==" }, "terser": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.0.tgz", - "integrity": "sha512-sgQ99P+fRBM1jAYzN9RTnD/xEWx/7LZgYTCRgmYriSq1wxxqiQPJgXkkLBBuwySDWJ2PP0PnVQyuf4xLUuH4Ng==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "dependencies": { @@ -22702,55 +22323,19 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "requires": { - "whatwg-url": "^7.0.0" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } } } }, "terser-webpack-plugin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", - "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", "requires": { + "@jridgewell/trace-mapping": "^0.3.14", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "dependencies": { "schema-utils": { @@ -22762,11 +22347,6 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -22830,7 +22410,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "trim": { "version": "0.0.1", @@ -23029,7 +22609,16 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } }, "update-notifier": { "version": "5.1.0", @@ -23135,7 +22724,7 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "8.3.2", @@ -23150,7 +22739,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "vfile": { "version": "4.2.1", @@ -23222,7 +22811,7 @@ "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "webpack": { "version": "5.73.0", @@ -23269,11 +22858,6 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" } } }, @@ -23301,12 +22885,12 @@ } }, "webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", "requires": { "colorette": "^2.0.10", - "memfs": "^3.4.1", + "memfs": "^3.4.3", "mime-types": "^2.1.31", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" @@ -23350,9 +22934,9 @@ } }, "webpack-dev-server": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz", - "integrity": "sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz", + "integrity": "sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw==", "requires": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -23366,7 +22950,7 @@ "chokidar": "^3.5.3", "colorette": "^2.0.10", "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", + "connect-history-api-fallback": "^2.0.0", "default-gateway": "^6.0.3", "express": "^4.17.3", "graceful-fs": "^4.2.6", @@ -23421,9 +23005,9 @@ } }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", "requires": {} } } @@ -23438,20 +23022,9 @@ } }, "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" }, "webpackbar": { "version": "5.0.2", @@ -23482,7 +23055,7 @@ "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" diff --git a/package.json b/package.json index c4f889f..b27644e 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ }, "dependencies": { "@cmfcmf/docusaurus-search-local": "^0.9.4", - "@docusaurus/core": "^2.0.0-beta.21", - "@docusaurus/preset-classic": "^2.0.0-beta.21", + "@docusaurus/core": "^2.0.0-rc.1", + "@docusaurus/preset-classic": "^2.0.0-rc.1", "@easyops-cn/docusaurus-search-local": "^0.26.1", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", diff --git a/restapi_versioned_docs/version-REST API 2.10.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.10.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md new file mode 100644 index 0000000..b904728 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. + +[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.10.0/restendpoints.md new file mode 100644 index 0000000..5056f71 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restendpoints.md @@ -0,0 +1,273 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md new file mode 100644 index 0000000..91afd98 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md new file mode 100644 index 0000000..5094407 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -0,0 +1,616 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Flag to enable or explicitly disable the duplicate transansaction verification in the payments flow. | + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} + +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.10.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md new file mode 100644 index 0000000..cebd56f --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md @@ -0,0 +1,33 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.10.0 +**Features:** +- New optional "Duplicate check" flag which enables the duplicate payments verification in the transaction flow. + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.10.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.10.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.10.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.10.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.10.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index be6def8..e8d2ef4 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,5 +1,5 @@ [ + "REST API 2.10.0", "REST API 2.7.1", "REST API 2.6.0" - ] From 171d4c192a345515657871da59315726896b1378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Fri, 23 Sep 2022 10:56:30 +0200 Subject: [PATCH 018/115] SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7440cdb..1c34961 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,4 @@ Every time we want to integrate changes from a feature branch to the `dev` branc If you are writing documentation for a new version, you have to follow the steps in the section [Generate a new SDK version](#generate-a-new-sdk-version) before merging to `main` branch. Once the changes are tested in the staging environment, another PR has to be created to merge the changes from `dev` branch to `main` branch. This PR will be reviewed by two team members and merged to `main` branch. This will trigger a deployment to the production environment (It can take up to 5 minutes to be deployed). + From 3366bca4f578a895da03b479708e63400843945a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Fri, 23 Sep 2022 11:15:36 +0200 Subject: [PATCH 019/115] SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol --- .../javascriptmethods.md | 550 ++++++++++++++++++ yarn.lock | 4 +- 2 files changed, 552 insertions(+), 2 deletions(-) create mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md new file mode 100644 index 0000000..0375310 --- /dev/null +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md @@ -0,0 +1,550 @@ +--- +sidebar_position: 9 +id: javascriptmethods +--- + +# Methods + +## Initialize{#1} + +`Initialize` + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The Actor API key.| +| `dev_or_prod_environment` Required
*boolean* | Value that defines if the actor is targeting a development (true -> cloud.handpoint.io) or production (false -> cloud.handpoint.com) environment.| +| `recovery_EoT_callback` Required
*promise* |Promise that collects the pending transaction results that couldn't be delivered to the POS during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the reader. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may just return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of Device objects| + + +## Connect{#2} + +`Connect` + +Connect the JavaScript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the init call.| + +**Code example** + +```javascript +Handpoint.connect('1234263-TYPE1'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|- **200** code for OK
- **403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` + +Connect the JavaScript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the init call.| + +**Code example** + +```javascript +Handpoint.connect('1234263-TYPE1'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|- `Disconnected` message for OK
- `ERROR disconnecting` message for NOK| + + +## Sale{#4} + +`Sale` + +A sale initiates a payment operation to the card reader. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var [*SaleOptions*](#23) = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.sale('1000', 'USD', [*SaleOptions*](#23) , function (stat) { + console.log('Transaction Status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|A Financial Response object| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` + +A sale which both authorizes the transaction and returns a token representing the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var [*SaleOptions*](#23) = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleAndTokenization('1000', 'USD', [*SaleOptions*](#23) , CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale and Tokenization Response**|A Financial Response object| + + +## Transaction Recovery{#6} + +`StartRecovery` + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the device| +| **Promise Error Response**|The event was not sent to the terminal because it is unreachable| + +## Stop Listening Device{#7} + +`StopListeningDevice` + +This operation interrupts the connection, stops listening to transaction events and resets the connection with the device + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` + +## Sale Reversal{#8} + +`SaleReversal` + +A sale Reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|A Financial Response object| + + +## Refund{#9} + +`Refund` + +A refund initiates a refund operation to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `refundOptions` Required
[*RefundOptions*](javascriptobjects.md#24) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|A Financial Response object| + + +## Refund Reversal{#10} + +`RefundReversal` + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the charge| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| +| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a refundReversal. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Reversal Response**|A Financial Response object| + + + +## Tokenize Card{#11} + +`TokenizeCard` + +Returns a token for the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|A Financial Response object| + + +## Card Pan{#12} + +`CardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|A Financial Response object| + + +## Stop Current Transaction{#13} + +`StopCurrentTransaction` + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of a payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` + +This method sends the merchant or customer receipt to the terminal for printing. The format of the HTML data, passed to the method or stored in the url, must follow this format: Html Print Format. + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific Status object that describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object| + +## Update{#16} + +`Update` + +Triggers a terminal software and config update + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A Financial Response object| + diff --git a/yarn.lock b/yarn.lock index 6e13961..32ad846 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,7 +1228,7 @@ "@docsearch/css" "3.2.1" algoliasearch "^4.0.0" -"@docusaurus/core@2.1.0", "@docusaurus/core@^2.0.0-beta.21": +"@docusaurus/core@2.1.0", "@docusaurus/core@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.1.0.tgz#4aedc306f4c4cd2e0491b641bf78941d4b480ab6" integrity sha512-/ZJ6xmm+VB9Izbn0/s6h6289cbPy2k4iYFwWDhjiLsVqwa/Y0YBBcXvStfaHccudUC3OfP+26hMk7UCjc50J6Q== @@ -1465,7 +1465,7 @@ sitemap "^7.1.1" tslib "^2.4.0" -"@docusaurus/preset-classic@^2.0.0-beta.21": +"@docusaurus/preset-classic@^2.0.0-rc.1": version "2.1.0" resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.1.0.tgz#45b23c8ec10c96ded9ece128fac3a39b10bcbc56" integrity sha512-NQMnaq974K4BcSMXFSJBQ5itniw6RSyW+VT+6i90kGZzTwiuKZmsp0r9lC6BYAvvVMQUNJQwrETmlu7y2XKW7w== From 45da5253b09198d5bd5f70251499e892a0c27e98 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 23 Sep 2022 14:36:35 +0200 Subject: [PATCH 020/115] Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 --- docusaurus.config.js | 2 +- windows/windowsreleasenotes.md | 11 +++++++++++ windows/windowstransactions.md | 10 +++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index ad61b49..8453cea 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -250,7 +250,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 7a7605b..44405d7 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -9,6 +9,17 @@ id: windowsreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 3.3.0 +**Features:** +- The new Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). + +Here is an example of how to disable it: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + ## 3.2.5 **Fixes:** diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index ad1653b..1fdbe25 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -6,6 +6,10 @@ id: windowstransactions # Transaction Types +:::warning +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + ## Sale `Sale` Method @@ -28,10 +32,10 @@ A sale initiates a transaction with the payment terminal. In it's simplest form this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); // With options -Dictionary dic = new Dictionary(); -dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); -this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, dic); +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); ``` #### Events invoked From 553d3386aae333139f9bcb6c2b9fe3c586d7e319 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 23 Sep 2022 17:49:46 +0200 Subject: [PATCH 021/115] Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 --- windows/windowsobjects.md | 3 +- windows/windowstransactions.md | 2 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 360 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 1951 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 514 +++++ .../windowsreleasenotes.md | 59 + .../windowstransactions.md | 562 +++++ .../version-Windows SDK 3.3.0-sidebars.json | 8 + windows_versions.json | 1 + 13 files changed, 3842 insertions(+), 2 deletions(-) create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.3.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 3.3.0-sidebars.json diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index f4ab24e..c776fb2 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -398,8 +398,9 @@ A class containing optional transaction parameters now supported by the device. |Property| Description| | ----------- | ----------- | -|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*|**String DuplicateCheck is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is enabled by default. If you want to disable it, you must use the `String` "0" Example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| ## Log Level{#9} diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 1fdbe25..b0c7281 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -6,7 +6,7 @@ id: windowstransactions # Transaction Types -:::warning +:::caution Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). ::: diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md new file mode 100644 index 0000000..09b7ce9 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md @@ -0,0 +1,360 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.UseDevice(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.UseDevice(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set parameter + +`SetParameter` Method + +Allows developers to optionally change several internal parameters of the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| +| `value` Required
*String* | New value of the parameter.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Changes the bluetooth name of card reader +api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md new file mode 100644 index 0000000..5d410ec --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md new file mode 100644 index 0000000..f58da30 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md @@ -0,0 +1,1951 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void **[*deviceDiscoveryFinished*](#13)**(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + // Put the name of your device, it is the composition of: serial number - device model. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void **[*deviceDiscoveryFinished*](#13)**(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md new file mode 100644 index 0000000..c776fb2 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md @@ -0,0 +1,514 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*|**String DuplicateCheck is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is enabled by default. If you want to disable it, you must use the `String` "0" Example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md new file mode 100644 index 0000000..44405d7 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md @@ -0,0 +1,59 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 3.3.0 +**Features:** +- The new Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). + +Here is an example of how to disable it: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + + +## 3.2.5 +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowstransactions.md new file mode 100644 index 0000000..b0c7281 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowstransactions.md @@ -0,0 +1,562 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Requiredv*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| diff --git a/windows_versioned_sidebars/version-Windows SDK 3.3.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 3.3.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 3.3.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index ede2795..7ccd894 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 3.3.0", "Windows SDK 3.2.5", "Windows SDK 3.2.4", "Windows SDK 3.2.0" From ad97a13a69a30f4da6bde1d94e8676cd1cbd0cf4 Mon Sep 17 00:00:00 2001 From: adrianfrez Date: Tue, 27 Sep 2022 10:36:26 +0200 Subject: [PATCH 022/115] Migration Guide v7 (#33) some small changes related to OperationStartResult --- android/androidintegrationguide.md | 6 +++--- android/androidmigrationguide.md | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index ca44b6a..edb1d2d 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -201,13 +201,13 @@ public class HandpointDelegate implements Events.Required, Events.ConnectionStat // This event can be safely ignored for a PAX/Telpo integration } - public boolean pay() { + public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); // Let´s start our first payment of 10 pounds // Use the currency of the country in which you will be deploying terminals } - public boolean payWithOptions() { + public OperationStartResult payWithOptions() { SaleOptions options = new SaleOptions(); // Adding tipping @@ -493,7 +493,7 @@ public class HandpointDelegate implements Events.Required, Events.ConnectionStat } } - public boolean pay() { + public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); // Let´s start our first payment of 10 pounds } diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 4e3f46a..6b9eb6a 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -207,6 +207,8 @@ With the aim of improving the information on our customers' transactions, now, H ## 3. Disable Duplicate Check service{#4} +**This service is only available on Smartpos Integrations.** + By default our Duplicate Check service is enabled. To disable the Duplicate Check service, set the `checkDuplicate` field to false for the corresponding operations, as in the following example: ```java From 4aeb3f8bbad63c42267eab8158ec7f58fbf2a71f Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Tue, 27 Sep 2022 16:03:21 +0200 Subject: [PATCH 023/115] SDK-2972 (#34) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado --- .../version-Javascript SDK 6.2.0/javascriptobjects.md | 4 ++-- .../version-Javascript SDK 6.2.0/javascriptreleasenotes.md | 2 +- .../version-REST API 2.10.0/restobjects.md | 6 +++--- .../version-REST API 2.10.0/restreleasenotes.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md index 0a0e6b1..248e751 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -267,7 +267,7 @@ An object to store the customization options for a sale operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Flag to select the duplicate check payments flow.| +| `duplicate_check`
*Boolean* | Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified).| | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| @@ -317,7 +317,7 @@ An object to store the customization options for a refund. This object can be em | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Flag to select the duplicate check payments flow.| +| `duplicate_check`
*Boolean* | Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified). | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md index 912b5d6..24f323e 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md @@ -13,7 +13,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 6.2.0 **Features**: -- New "Duplicate check" flag which enables the duplicate payments checking transaction flow. +- New "Duplicate check" flag to explicitly disable the duplicate check payments flow. If the flag is not present (or if it is true), this flow is enabled by default. ## 6.1.0 diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index 5094407..b3d1a0d 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -221,7 +221,7 @@ An object to store information about the request sent to the payment terminal. | `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | -| `duplicate_check`
*Boolean* |Flag to enable or explicitly disable the duplicate transansaction verification in the payments flow. | +| `duplicate_check`
*Boolean* |Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified). | **Code example** @@ -254,7 +254,7 @@ An object to store information about the request sent to the payment terminal. "mcc": "3333", "externalId": "4444" }], - "duplicate_check": true + "duplicate_check": false } // Result will be served back to Handpoint's REST-API @@ -283,7 +283,7 @@ An object to store information about the request sent to the payment terminal. "mcc": "3333", "externalId": "4444" }], - "duplicate_check": true + "duplicate_check": false } ```` diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md index cebd56f..98619b2 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md @@ -11,7 +11,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.10.0 **Features:** -- New optional "Duplicate check" flag which enables the duplicate payments verification in the transaction flow. +- New "Duplicate check" flag to explicitly disable the duplicate check payments flow. If the flag is not present (or if it is true), this flow is enabled by default. ## 2.7.1 **Features:** From 6ce98f0b74ae0949fdca7b56d42d915ad9c9f459 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 28 Sep 2022 12:53:24 -0400 Subject: [PATCH 024/115] Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos --- android/androideventlisteners.md | 122 +- android/androideventsubscribers.md | 4 +- android/androidintegrationguide.md | 16 +- android/androidmigrationguide.md | 122 +- android/androidobjects.md | 14 +- android/androidreleasenotes.md | 8 + android/androidtransactions.md | 24 +- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 368 ++++++ .../androideventlisteners.md | 700 ++++++++++++ .../androideventsubscribers.md | 73 ++ .../androidintegrationguide.md | 542 +++++++++ .../androidintroduction.md | 148 +++ .../androidmigrationguide.md | 259 +++++ .../androidobjects.md | 1013 +++++++++++++++++ .../androidreleasenotes.md | 214 ++++ .../androidtransactions.md | 578 ++++++++++ .../version-Android SDK 7.0.0-sidebars.json | 8 + android_versions.json | 1 + docusaurus.config.js | 2 +- javascript/javascriptintroduction.md | 4 +- javascript/javascriptmethods.md | 550 --------- javascript/javascriptobjects.md | 4 + javascript/javascriptquickintegration.md | 2 +- javascript/javascriptreleasenotes.md | 10 + .../javascriptmethods.md | 550 --------- .../javascriptobjects.md | 4 +- .../javascriptquickintegration.md | 2 +- .../javascriptreleasenotes.md | 7 +- restapi/restobjects.md | 7 +- restapi/restreleasenotes.md | 9 + .../version-REST API 2.10.0/restobjects.md | 2 +- .../restreleasenotes.md | 9 +- windows/windowsobjects.md | 2 +- windows/windowsreleasenotes.md | 10 +- .../windowsobjects.md | 2 +- .../windowsreleasenotes.md | 10 +- 37 files changed, 4191 insertions(+), 1231 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.0.0-sidebars.json delete mode 100644 javascript/javascriptmethods.md delete mode 100644 javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md diff --git a/android/androideventlisteners.md b/android/androideventlisteners.md index 6162f34..93ffb87 100644 --- a/android/androideventlisteners.md +++ b/android/androideventlisteners.md @@ -8,26 +8,102 @@ id: androideventlisteners # Events Listeners -## All +## SmartposRequired -`Events.All` Interface +`Events.SmartposRequired` Interface -An interface which needs to be implemented and added as a listener to receive all available events. +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). -**Extends** +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } -[`Required`](#42) [`Log`](#log) [`Status`](#status) [`PendingResults`](#pendingResults) [`ReportResult`](#reportResult) [`PrinterEvents`](#printerEvents) [`TransactionStarted`](#transactionStarted) [`MessageHandling`](#messageHandling) [`PhysicalKeyboardEvent`](#physicalKeyboardEvent) [`CardBrandDisplay`](#cardBrandDisplay) +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +**Events** -## Basic + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) -`Events.Basic` Interface -An interface which needs to be implemented and added as a listener to receive basic events. +## MposRequired -**Extends** +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface -[`Required`](#42) [`Log`](#log) [`Status`](#status) [`PendingResults`](#pendingResults) [`ReportResult`](#reportResult) +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) ## Card Brand Display{#cardBrandDisplay} @@ -493,32 +569,6 @@ public final class EventHandler implements Events.ReportResult { this.api.registerEventsDelegate(eventHandlerInstance); ``` -## Required{#42} - -`Events.Required` Interface - -You must provide a class implementing this interface when initializing the SDK. - -**Code example** - -```java -public final class EventHandler implements Events.Required { - - @Override - public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } - @Override - public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } - @Override - public void deviceDiscoveryFinished(List devices) { ... } - @Override - public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } - -} - -// Remember to register the instance of this EventHandler: -this.api.registerEventsDelegate(eventHandlerInstance); -``` - **Events** [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) diff --git a/android/androideventsubscribers.md b/android/androideventsubscribers.md index 7b2974e..a997f42 100644 --- a/android/androideventsubscribers.md +++ b/android/androideventsubscribers.md @@ -21,7 +21,7 @@ Registers a delegate for the SDK events. **Code example** ```java -public class ObjectHelper implements Events.Required, Events.Status, Events.Log, Events.PendingResults, Events.TransactionStarted { +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { ... private void setEventsHandler() { // Register this class as listener for events @@ -55,7 +55,7 @@ Unregisters an object from SDK events. **Code example** ```java -public class ObjectHelper implements Events.Required, Events.Status, Events.Log, Events.PendingResults, Events.TransactionStarted { +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { ... private void unsubscribeEventsDelegate() { // Stop receiving events diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index edb1d2d..b6138e7 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -167,7 +167,7 @@ import java.util.List; //Check all the events available in the Events interface. //If you want to subscribe to more events, just add to the list of implemented interfaces. -public class HandpointDelegate implements Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { private Hapi api; @@ -196,11 +196,6 @@ public class HandpointDelegate implements Events.Required, Events.ConnectionStat } } - @Override - public void deviceDiscoveryFinished(List devices) { - // This event can be safely ignored for a PAX/Telpo integration - } - public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); // Let´s start our first payment of 10 pounds @@ -261,13 +256,6 @@ public class HandpointDelegate implements Events.Required, Events.ConnectionStat } } - @Override - public void signatureRequired(SignatureRequest signatureRequest, Device device) { - // This event can be safely ignored for a PAX/Telpo integration - // The complete signature capture process is already handled in the sdk, a dialog will prompt the user for a signature if required. - // If a signature was entered, it should be printed on the receipts. - } - @Override public void endOfTransaction(TransactionResult transactionResult, Device device) { // The TransactionResult object holds details about the transaction as well as the receipts @@ -424,7 +412,7 @@ import java.util.List; //Check all the events available in the Events interface. //If you want to subscribe to more events, just add to the list of implemented interfaces. -public class HandpointDelegate implements Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { private Hapi api; diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 6b9eb6a..4a88c63 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -7,25 +7,52 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Migration from 6.X to 7.X{#1} -The new version 7.X of our Android SDK introduces the next changes: -- Removed the **Required** Interface and created [3 new Interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. -- The [operations described below](androidmigrationguide.md#3), return the [OperationStartResult](androidobjects.md#operation-start-result) object instead of a `boolean`. -- The new Duplicate Check service **is enabled by default**. To disable it, please check this [section](androidmigrationguide.md#4). -- `deviceCapabilities` event of CardBrandDisplay Interface has been renamed. +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` -## 1. New integration Interfaces +## 1. New Interfaces -For an easier integration with our SDK, we have created 3 interfaces, which have each of the mandatory events to be implemented correctly: +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: -- **SmartposRequired**: Android Native Integration (PAX/Telpo) -- **MposRequired**: for Bluetooth integrations (HiLite) -- **PosRequired**: For integrations that include both +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. -The changes required in each of the scenarios are described below. +Here is the list of events being part of each interface: +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` -### Android Native Integration +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) #### Older Implementation (Android SDK 6.X) @@ -36,9 +63,7 @@ public class HandpointDelegate implements Events.Required, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, - Events.SignatureRequired, Events.EndOfTransaction, - Events.DeviceDiscoveryFinished, Events.TransactionResultReady { ``` @@ -48,9 +73,9 @@ public class HandpointDelegate implements ```java class KotlinClient: - Events.Required, - Events.ConnectionStatusChanged, - Events.CurrentTransact { + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { ``` @@ -61,12 +86,12 @@ class KotlinClient: ```java -public class HandpointDelegate implements - Events.SmartposRequired, - Events.CurrentTransactionStatus, - Events.ConnectionStatusChanged, - Events.EndOfTransaction, - Events.TransactionResultReady { +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { ``` @@ -80,7 +105,7 @@ class KotlinClient: Events.SmartposRequired { -### Bluetooth Integration +### Bluetooth Integration (HiLite) #### Older Implementation (Android SDK 6.X) @@ -102,7 +127,10 @@ public class HandpointDelegate implements ```java -class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { ``` @@ -115,12 +143,12 @@ class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.Curr ```java public class JavaClient implements Events.MposRequired, - Events.CurrentTransactionStatus, - Events.ConnectionStatusChanged, - Events.SignatureRequired, - Events.EndOfTransaction, - Events.DeviceDiscoveryFinished, - Events.TransactionResultReady + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { ``` @@ -134,7 +162,7 @@ class KotlinClient: Events.MposRequired { -### Bluetooth and Android Native Integration +### Bluetooth and Android Native Integration (PAX & HiLite) #### Older Implementation (Android SDK 6.X) @@ -156,7 +184,10 @@ public class HandpointDelegate implements ```java -class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { ``` @@ -169,12 +200,12 @@ class KotlinClient: Events.Required, Events.ConnectionStatusChanged, Events.Curr ```java public class JavaClient implements Events.PosRequired, + Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, - Events.ConnectionStatusChanged, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, - Events.TransactionResultReady + Events.TransactionResultReady { ``` @@ -189,9 +220,9 @@ class KotlinClient: Events.PosRequired { -## 2. [OperationStartResult](androidobjects.md#operation-start-result) class is returned now on Hapi Operations{#3} +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} -With the aim of improving the information on our customers' transactions, now, Hapi object returns this class instead of a boolean. The methods that are affected by this change, and that should be modified for a correct implementation are the following: +The methods affected by this change are the following: - [Sale](androidtransactions.md#2) - [Sale and Tokenize](androidtransactions.md#3) @@ -205,11 +236,11 @@ With the aim of improving the information on our customers' transactions, now, H - [CardPan](androidtransactions.md#13) -## 3. Disable Duplicate Check service{#4} +## 3. Disabling the duplicate payment check service{#4} -**This service is only available on Smartpos Integrations.** +**This functionality is only available for SmartPos devices (PAX).** -By default our Duplicate Check service is enabled. To disable the Duplicate Check service, set the `checkDuplicate` field to false for the corresponding operations, as in the following example: +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: ```java public void pay(BigInteger amount, Currency currency) { @@ -218,12 +249,11 @@ public void pay(BigInteger amount, Currency currency) { this.api.sale(amount, currency, saleOptions); } ``` -This step applies for the followings operations: -- [Sale](androidtransactions.md#2) and [Sale and Tokenize](androidtransactions.md#3) +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) - [Refund](androidtransactions.md#5) -## 4. Renamed event deviceCapabilities of CardBrandDisplay Interface - -Changed the name of the event `deviceCapabilities` of CardBrandDisplay Interface. Now `deviceCapabilities` is called `supportedCardBrands`. +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` -Check [here](androideventlisteners.md#cardBrandDisplay) all the necessary information. \ No newline at end of file + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file diff --git a/android/androidobjects.md b/android/androidobjects.md index 0176d5d..e3de1cf 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -651,14 +651,14 @@ options.setChannel(MoToChannel.TO); `OperationStartResult` Object -Object that contains information about the operation performed. +Object containing information about the financial operation being performed. **Properties** | Parameter | Description | | ----------- | ----------- | -| `operationStarted`
*boolean* | `true` The operation has started. | -| `transactionReference`
*String* | Identification of the operation throughout its life cycle. | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| | `errorMessage`
*String* | Detailed reason for the transaction error. | @@ -740,6 +740,7 @@ An object to store all the customization options for a refund. | `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| | `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| **Code example** @@ -764,6 +765,9 @@ options.setMerchantAuth(auth); //If you need to enable pin bypass options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); ``` ## Report Configuration{#19} @@ -808,6 +812,7 @@ An object to store all the customization options for a sale. | `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| **Code example** @@ -833,6 +838,9 @@ options.setMerchantAuth(auth); //If you need to enable pin bypass options.setPinBypass(true); +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + //If you want to specify the budget period //Only available for SureSwipe options.setBudgetNumber(YOUR_BUDGET_NUMBER); diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index a9fb6a1..b282f04 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,14 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.0.0 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + ## 6.7.4 - `customerReference` correctly populated when card is removed in the middle of a transaction diff --git a/android/androidtransactions.md b/android/androidtransactions.md index e65da9d..fda30c2 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -3,7 +3,7 @@ sidebar_position: 5 id: androidtransactions --- -# Transactions +# Transaction Types @@ -65,7 +65,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Sale And Tokenize Card{#3} @@ -125,7 +125,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -173,7 +173,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund{#5} @@ -220,7 +220,7 @@ Invoked when the terminal finishes processing the transaction | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund reversal{#6} @@ -267,7 +267,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Sale{#7} @@ -312,7 +312,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -358,7 +358,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Reversal{#9} @@ -401,7 +401,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Signature result @@ -443,7 +443,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -536,7 +536,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Card PAN{#13} @@ -575,4 +575,4 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object that contains information about the operation performed.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.0.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md new file mode 100644 index 0000000..af0bcb8 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md @@ -0,0 +1,368 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.0.0/androideventlisteners.md new file mode 100644 index 0000000..93ffb87 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androideventlisteners.md @@ -0,0 +1,700 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { + // Notify the app user transaction has been started ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.0.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md new file mode 100644 index 0000000..b6138e7 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md @@ -0,0 +1,542 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue + // For this sample app we are not going to implement this event + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:6.x.x' + + //Handpoint Staging/Development SDK (Debug devices) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +```groovy +allprojects { //Handpoint Staging/Development SDK + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") + credentials { + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md new file mode 100644 index 0000000..3227ab0 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md @@ -0,0 +1,148 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 5.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 6.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +### Gradle Settings + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md new file mode 100644 index 0000000..4a88c63 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md @@ -0,0 +1,259 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md new file mode 100644 index 0000000..e3de1cf --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md @@ -0,0 +1,1013 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. +12:06 +From 7.1.0 we won't cancel transactions anymore and will use getTxnStatus to return the actual status of the transaction ( | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMerchantId(mid); +//Optionally +credential1.setTerminalId(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md new file mode 100644 index 0000000..b282f04 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md @@ -0,0 +1,214 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.0.0 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md new file mode 100644 index 0000000..fda30c2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md @@ -0,0 +1,578 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +`saleAndTokenizeCard` + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with tipping configuration +//This feature is not available for HiLite & Hi5 devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); + +api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.0.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.0.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 415a79e..b95bf3f 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.0.0", "Android SDK 6.7.4", "Android SDK 6.7.2" ] diff --git a/docusaurus.config.js b/docusaurus.config.js index 8453cea..ad61b49 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -250,7 +250,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index 09934c8..2b68489 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript/javascriptmethods.md b/javascript/javascriptmethods.md deleted file mode 100644 index 0375310..0000000 --- a/javascript/javascriptmethods.md +++ /dev/null @@ -1,550 +0,0 @@ ---- -sidebar_position: 9 -id: javascriptmethods ---- - -# Methods - -## Initialize{#1} - -`Initialize` - -Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `API_key` Required
*string* | The Actor API key.| -| `dev_or_prod_environment` Required
*boolean* | Value that defines if the actor is targeting a development (true -> cloud.handpoint.io) or production (false -> cloud.handpoint.com) environment.| -| `recovery_EoT_callback` Required
*promise* |Promise that collects the pending transaction results that couldn't be delivered to the POS during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the reader. The sdk has a 5 second window for the promise to be resolved | - -**Code example** - -```javascript -Handpoint.init('API KEY', true, (pendingEoT) => { - console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); - return handleTransactionResultPromise(pendingEoT); -}) - -// For simple or sync operations you may just return a resolved Promise. -Handpoint.init('API KEY', true, (pendingEoT) => { - console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); - return Promise.resolve(); -}) -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Devices**| List of Device objects| - - -## Connect{#2} - -`Connect` - -Connect the JavaScript SDK to a payment terminal. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the init call.| - -**Code example** - -```javascript -Handpoint.connect('1234263-TYPE1'); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Connection Result**|- **200** code for OK
- **403** code for NOK| - - -## Disconnect{#3} - -`Disconnect` - -Connect the JavaScript SDK to a payment terminal. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the init call.| - -**Code example** - -```javascript -Handpoint.connect('1234263-TYPE1'); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Connection Result**|- `Disconnected` message for OK
- `ERROR disconnecting` message for NOK| - - -## Sale{#4} - -`Sale` - -A sale initiates a payment operation to the card reader. In its simplest form, you only have to pass the amount and currency as parameters. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| -| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var [*SaleOptions*](#23) = { - customerReference: "MyCustomReference", - tipConfiguration: { - baseAmount: "100", - skipEnabled: true, - enterAmountEnabled: true, - tipPercentages: [ - 1, - 2, - 3, - 5 - ] - }, - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.sale('1000', 'USD', [*SaleOptions*](#23) , function (stat) { - console.log('Transaction Status received -> '+ stat.message) -}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale Response**|A Financial Response object| - - - -## Sale And Tokenization{#5} - -`SaleAndTokenization` - -A sale which both authorizes the transaction and returns a token representing the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var [*SaleOptions*](#23) = { - customerReference: "MyCustomReference", - tipConfiguration: { - baseAmount: "100", - skipEnabled: true, - enterAmountEnabled: true, - tipPercentages: [ - 1, - 2, - 3, - 5 - ] - }, - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.saleAndTokenization('1000', 'USD', [*SaleOptions*](#23) , CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale and Tokenization Response**|A Financial Response object| - - -## Transaction Recovery{#6} - -`StartRecovery` - -The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). - -For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). - -The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true - -**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** - -**Code example** - -```javascript -//Start recovery of pending transactions -Handpoint.startRecovery(); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Promise Successful Response**|The event has been sent to the device| -| **Promise Error Response**|The event was not sent to the terminal because it is unreachable| - -## Stop Listening Device{#7} - -`StopListeningDevice` - -This operation interrupts the connection, stops listening to transaction events and resets the connection with the device - - -**Code example** - -```javascript -//Stop Listening to Events -Handpoint.stopListeningDevice(); -``` - -## Sale Reversal{#8} - -`SaleReversal` - -A sale Reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var saleReversalOptions = { - customerReference: "MyCustomReference", - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale Reversal Response**|A Financial Response object| - - -## Refund{#9} - -`Refund` - -A refund initiates a refund operation to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `refundOptions` Required
[*RefundOptions*](javascriptobjects.md#24) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var refundOptions = { - customerReference: "MyCustomReference", - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); - -// Linked Refund -Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Refund Response**|A Financial Response object| - - -## Refund Reversal{#10} - -`RefundReversal` - -A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a refundReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var refundOptions = { - customerReference: "MyCustomReference", - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); - -// Linked Refund -Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Refund Reversal Response**|A Financial Response object| - - - -## Tokenize Card{#11} - -`TokenizeCard` - -Returns a token for the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var options = { - customerReference: "MyCustomReference", -} - -Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Tokenize Card Response**|A Financial Response object| - - -## Card Pan{#12} - -`CardPan` - -A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var options = { - customerReference: "MyCustomReference", -} - -Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Card Pan Response**|A Financial Response object| - - -## Stop Current Transaction{#13} - -`StopCurrentTransaction` - -Operation used to stop the current transaction. The transaction can only be stopped at specific stages of a payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. - - -**Code example** - -```javascript -Handpoint.stopCurrentTransaction(); - -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| -| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| -| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| - - -## Print Receipt{#14} - -`PrintReceipt` - -This method sends the merchant or customer receipt to the terminal for printing. The format of the HTML data, passed to the method or stored in the url, must follow this format: Html Print Format. - - -**Code example** - -```javascript -Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); - -var htmlReceipt = '[...] HTML receipt [...]' - -Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); -``` -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Print Receipt Response**|A specific Status object that describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| - - -## Ping Device{#15} - -`PingDevice` - -This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping - -**Code example** - -```javascript -Handpoint.pingDevice(CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object| - -## Update{#16} - -`Update` - -Triggers a terminal software and config update - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -Handpoint.update(CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Update Response**|A Financial Response object| - diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 2fe2348..3380930 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -267,6 +267,7 @@ An object to store the customization options for a sale operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| @@ -276,6 +277,7 @@ An object to store the customization options for a sale operation. This object c ```json { "customerReference": "MyCustomReference", + "duplicate_check": false, "tipConfiguration": { "baseAmount": "100", "skipEnabled": true, @@ -315,12 +317,14 @@ An object to store the customization options for a refund. This object can be em | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| ```json { "customerReference": "MyCustomReference", + "duplicate_check": false, "tipConfiguration": { "baseAmount": "100", "skipEnabled": true, diff --git a/javascript/javascriptquickintegration.md b/javascript/javascriptquickintegration.md index 23133c6..f3e18ce 100644 --- a/javascript/javascriptquickintegration.md +++ b/javascript/javascriptquickintegration.md @@ -84,7 +84,7 @@ The following example shows how you can integrate your web application with the :::tip Maintain the connection with the terminal at all times: -- To be able to recover a transaction result through the callback passed in the [*init*](javascriptmethods.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. - Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. How Transaction Recovery Works: diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 1e9ba30..2ba0e6b 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -10,6 +10,16 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + ## 6.1.0 **Features**: diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md deleted file mode 100644 index 0375310..0000000 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptmethods.md +++ /dev/null @@ -1,550 +0,0 @@ ---- -sidebar_position: 9 -id: javascriptmethods ---- - -# Methods - -## Initialize{#1} - -`Initialize` - -Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `API_key` Required
*string* | The Actor API key.| -| `dev_or_prod_environment` Required
*boolean* | Value that defines if the actor is targeting a development (true -> cloud.handpoint.io) or production (false -> cloud.handpoint.com) environment.| -| `recovery_EoT_callback` Required
*promise* |Promise that collects the pending transaction results that couldn't be delivered to the POS during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the reader. The sdk has a 5 second window for the promise to be resolved | - -**Code example** - -```javascript -Handpoint.init('API KEY', true, (pendingEoT) => { - console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); - return handleTransactionResultPromise(pendingEoT); -}) - -// For simple or sync operations you may just return a resolved Promise. -Handpoint.init('API KEY', true, (pendingEoT) => { - console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); - return Promise.resolve(); -}) -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Devices**| List of Device objects| - - -## Connect{#2} - -`Connect` - -Connect the JavaScript SDK to a payment terminal. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the init call.| - -**Code example** - -```javascript -Handpoint.connect('1234263-TYPE1'); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Connection Result**|- **200** code for OK
- **403** code for NOK| - - -## Disconnect{#3} - -`Disconnect` - -Connect the JavaScript SDK to a payment terminal. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the init call.| - -**Code example** - -```javascript -Handpoint.connect('1234263-TYPE1'); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Connection Result**|- `Disconnected` message for OK
- `ERROR disconnecting` message for NOK| - - -## Sale{#4} - -`Sale` - -A sale initiates a payment operation to the card reader. In its simplest form, you only have to pass the amount and currency as parameters. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| -| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var [*SaleOptions*](#23) = { - customerReference: "MyCustomReference", - tipConfiguration: { - baseAmount: "100", - skipEnabled: true, - enterAmountEnabled: true, - tipPercentages: [ - 1, - 2, - 3, - 5 - ] - }, - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.sale('1000', 'USD', [*SaleOptions*](#23) , function (stat) { - console.log('Transaction Status received -> '+ stat.message) -}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale Response**|A Financial Response object| - - - -## Sale And Tokenization{#5} - -`SaleAndTokenization` - -A sale which both authorizes the transaction and returns a token representing the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store all the customisation options for a sale. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var [*SaleOptions*](#23) = { - customerReference: "MyCustomReference", - tipConfiguration: { - baseAmount: "100", - skipEnabled: true, - enterAmountEnabled: true, - tipPercentages: [ - 1, - 2, - 3, - 5 - ] - }, - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.saleAndTokenization('1000', 'USD', [*SaleOptions*](#23) , CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale and Tokenization Response**|A Financial Response object| - - -## Transaction Recovery{#6} - -`StartRecovery` - -The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). - -For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). - -The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true - -**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** - -**Code example** - -```javascript -//Start recovery of pending transactions -Handpoint.startRecovery(); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Promise Successful Response**|The event has been sent to the device| -| **Promise Error Response**|The event was not sent to the terminal because it is unreachable| - -## Stop Listening Device{#7} - -`StopListeningDevice` - -This operation interrupts the connection, stops listening to transaction events and resets the connection with the device - - -**Code example** - -```javascript -//Stop Listening to Events -Handpoint.stopListeningDevice(); -``` - -## Sale Reversal{#8} - -`SaleReversal` - -A sale Reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var saleReversalOptions = { - customerReference: "MyCustomReference", - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Sale Reversal Response**|A Financial Response object| - - -## Refund{#9} - -`Refund` - -A refund initiates a refund operation to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `refundOptions` Required
[*RefundOptions*](javascriptobjects.md#24) | An object to store all the customisation options for a saleReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var refundOptions = { - customerReference: "MyCustomReference", - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); - -// Linked Refund -Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Refund Response**|A Financial Response object| - - -## Refund Reversal{#10} - -`RefundReversal` - -A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount` Required
*integer* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Required
*string* | Currency of the charge| -| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization| -| `merchantAuthOptions` Required
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store all the customisation options for a refundReversal. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var refundOptions = { - customerReference: "MyCustomReference", - bypassOptions: { - signatureBypass: true, - pinBypass: true - }, - merchantAuth: [ - { - acquirer: "ACQUIRER", - mid: "11111", - tid: "22222", - mcc: "33333" - } - ], -} - -Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); - -// Linked Refund -Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Refund Reversal Response**|A Financial Response object| - - - -## Tokenize Card{#11} - -`TokenizeCard` - -Returns a token for the card. This feature is not available for all acquirers. Please check with Handpoint to know if tokenization is supported for your acquirer of choice - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var options = { - customerReference: "MyCustomReference", -} - -Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Tokenize Card Response**|A Financial Response object| - - -## Card Pan{#12} - -`CardPan` - -A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `options` Required
[*Options*](javascriptobjects.md#26) | An object to store all the customisation options for a tokenizeCard. This object can be empty if no options are required.| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -var options = { - customerReference: "MyCustomReference", -} - -Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Card Pan Response**|A Financial Response object| - - -## Stop Current Transaction{#13} - -`StopCurrentTransaction` - -Operation used to stop the current transaction. The transaction can only be stopped at specific stages of a payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. - - -**Code example** - -```javascript -Handpoint.stopCurrentTransaction(); - -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| -| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| -| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| - - -## Print Receipt{#14} - -`PrintReceipt` - -This method sends the merchant or customer receipt to the terminal for printing. The format of the HTML data, passed to the method or stored in the url, must follow this format: Html Print Format. - - -**Code example** - -```javascript -Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); - -var htmlReceipt = '[...] HTML receipt [...]' - -Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); -``` -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt| -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Print Receipt Response**|A specific Status object that describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| - - -## Ping Device{#15} - -`PingDevice` - -This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping - -**Code example** - -```javascript -Handpoint.pingDevice(CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object| - -## Update{#16} - -`Update` - -Triggers a terminal software and config update - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| - -**Code example** - -```javascript -Handpoint.update(CallbackFunction(stat){...}); -``` - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| **Update Response**|A Financial Response object| - diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md index 248e751..3380930 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -267,7 +267,7 @@ An object to store the customization options for a sale operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified).| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| @@ -317,7 +317,7 @@ An object to store the customization options for a refund. This object can be em | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified). +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md index 23133c6..f3e18ce 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptquickintegration.md @@ -84,7 +84,7 @@ The following example shows how you can integrate your web application with the :::tip Maintain the connection with the terminal at all times: -- To be able to recover a transaction result through the callback passed in the [*init*](javascriptmethods.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. - Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. How Transaction Recovery Works: diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md index 24f323e..2ba0e6b 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md @@ -13,7 +13,12 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 6.2.0 **Features**: -- New "Duplicate check" flag to explicitly disable the duplicate check payments flow. If the flag is not present (or if it is true), this flow is enabled by default. + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). ## 6.1.0 diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 35d5659..7e2e3a3 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -221,6 +221,7 @@ An object to store information about the request sent to the payment terminal. | `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| **Code example** @@ -252,7 +253,8 @@ An object to store information about the request sent to the payment terminal. "tid": "2222", "mcc": "3333", "externalId": "4444" - }] + }], + "duplicate_check": false } // Result will be served back to Handpoint's REST-API @@ -280,7 +282,8 @@ An object to store information about the request sent to the payment terminal. "tid": "2222", "mcc": "3333", "externalId": "4444" - }] + }], + "duplicate_check": false } ```` diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 7c03a9e..92aa143 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,15 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + ## 2.7.1 **Features:** - New endpoint to create, get and delete API keys for Merchants diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index b3d1a0d..7e2e3a3 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -221,7 +221,7 @@ An object to store information about the request sent to the payment terminal. | `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | -| `duplicate_check`
*Boolean* |Flag to disable the duplicate check payments flow (enabled - true if not otherwise specified). | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| **Code example** diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md index 98619b2..c657c23 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md @@ -11,7 +11,14 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.10.0 **Features:** -- New "Duplicate check" flag to explicitly disable the duplicate check payments flow. If the flag is not present (or if it is true), this flow is enabled by default. + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + + ## 2.7.1 **Features:** diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index c776fb2..b2dd3a7 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -400,7 +400,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*|**String DuplicateCheck is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is enabled by default. If you want to disable it, you must use the `String` "0" Example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| ## Log Level{#9} diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 44405d7..77c54d5 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -11,17 +11,23 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 3.3.0 **Features:** -- The new Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). -Here is an example of how to disable it: +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: ```csharp Dictionary options = new Dictionary(); options.Add(XmlTag.DuplicateCheck.Tag(), "0"); hapi.Sale(amount, currency, options); ``` +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) ## 3.2.5 + **Fixes:** - Nullpointer Exception on Cloud connect without network connection. - Cloud dependencies update. diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md index c776fb2..b2dd3a7 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md @@ -400,7 +400,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*|**String DuplicateCheck is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is enabled by default. If you want to disable it, you must use the `String` "0" Example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| ## Log Level{#9} diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md index 44405d7..77c54d5 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md @@ -11,17 +11,23 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 3.3.0 **Features:** -- The new Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). -Here is an example of how to disable it: +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: ```csharp Dictionary options = new Dictionary(); options.Add(XmlTag.DuplicateCheck.Tag(), "0"); hapi.Sale(amount, currency, options); ``` +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) ## 3.2.5 + **Fixes:** - Nullpointer Exception on Cloud connect without network connection. - Cloud dependencies update. From 1fa119d83ff9536b41eb65512e4bfee99e25c60f Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 5 Oct 2022 20:17:27 +0200 Subject: [PATCH 025/115] - fix: links pointing to correct section (#36) - fix: links pointing to correct site --- .../version-Android SDK 7.0.0/androidmigrationguide.md | 2 +- .../version-Android SDK 7.0.0/androidreleasenotes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md index 4a88c63..b6a6fb7 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md @@ -8,7 +8,7 @@ import TabItem from '@theme/TabItem'; # Migration from 6.X to 7.X{#1} The new version 7.X.X of our Android SDK introduces the following changes: -1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-interfaces) for a simpler and smoother integration. 2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md index b282f04..bc93474 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md @@ -13,7 +13,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 -- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-interfaces) - All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. - Introducing a new feature called **duplicate payment check**. - The `deviceCapabilities` event has been renamed to `supportedCardBrands` From 9abc676879a7999879303292558fb7bd1e3f4e79 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 7 Oct 2022 16:25:49 +0200 Subject: [PATCH 026/115] -add: Hubspot feature (#37) -add: Hubspot feature --- docusaurus.config.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docusaurus.config.js b/docusaurus.config.js index ad61b49..72869b8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -200,6 +200,11 @@ module.exports = { }, ], ], + scripts: [ + // String format. + 'https:////js-eu1.hs-scripts.com/25846579.js', + + ], plugins: [ // require.resolve('docusaurus-lunr-search', { From 3c47846077b08d5da572e1a41a3a0408c1dff121 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 25 Nov 2022 12:29:23 +0100 Subject: [PATCH 027/115] Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 --- android/androidintroduction.md | 2 +- android/androidobjects.md | 4 +--- android/androidtransactions.md | 16 +++++++++------- .../androidintroduction.md | 6 +++++- .../androidobjects.md | 4 +--- .../androidtransactions.md | 18 ++++++++++-------- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/android/androidintroduction.md b/android/androidintroduction.md index 3227ab0..92c9ef2 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -27,7 +27,7 @@ id: androidintroduction

:::tip -If you are currently using 5.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 6.x +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x ::: diff --git a/android/androidobjects.md b/android/androidobjects.md index e3de1cf..b8f5a96 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -375,9 +375,7 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. -12:06 -From 7.1.0 we won't cancel transactions anymore and will use getTxnStatus to return the actual status of the transaction ( | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | | `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| diff --git a/android/androidtransactions.md b/android/androidtransactions.md index fda30c2..6ecf95a 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -29,11 +29,11 @@ A sale initiates a payment operation to the card reader. In it's simplest form y //Initiate a sale for 10.00 in Great British Pounds api.sale(new BigInteger("1000"),Currency.GBP); -//Initiate a sale for 10.00 in Great British Pounds with tipping configuration +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration //This feature is only available for PAX and Telpo devices TipConfiguration tipConfiguration = new TipConfiguration(); tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); -tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setTipAmount(new BigInteger("1000")); tipConfiguration.setBaseAmount(new BigInteger("1000")); tipConfiguration.setEnterAmountEnabled(true); tipConfiguration.setFooter("Thank you"); @@ -87,21 +87,23 @@ A [sale](#2) operation which also returns a card token. (not available for all a ```java //Initiate a sale for 10.00 in Great British Pounds -api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); -//Initiate a sale for 10.00 in Great British Pounds with tipping configuration -//This feature is not available for HiLite & Hi5 devices +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices TipConfiguration tipConfiguration = new TipConfiguration(); tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); -tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setTipAmount(new BigInteger("1000")); tipConfiguration.setBaseAmount(new BigInteger("1000")); tipConfiguration.setEnterAmountEnabled(true); tipConfiguration.setFooter("Thank you"); tipConfiguration.setSkipEnabled(true); SaleOptions options = new SaleOptions(); options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); -api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP,options); +api.sale(new BigInteger("1000"),Currency.GBP,options); ``` **Events invoked** diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md index 3227ab0..cf8fda6 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md @@ -26,8 +26,12 @@ id: androidintroduction

+:::caution +**Handpoint recommends use the Android SDK 7.0.1 or higher.** +::: + :::tip -If you are currently using 5.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 6.x +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x ::: diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md index e3de1cf..b8f5a96 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md @@ -375,9 +375,7 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. -12:06 -From 7.1.0 we won't cancel transactions anymore and will use getTxnStatus to return the actual status of the transaction ( | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | | `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md index fda30c2..f2a8fbc 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md @@ -29,11 +29,11 @@ A sale initiates a payment operation to the card reader. In it's simplest form y //Initiate a sale for 10.00 in Great British Pounds api.sale(new BigInteger("1000"),Currency.GBP); -//Initiate a sale for 10.00 in Great British Pounds with tipping configuration -//This feature is only available for PAX and Telpo devices +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is not available for HiLite devices TipConfiguration tipConfiguration = new TipConfiguration(); tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); -tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setTipAmount(new BigInteger("1000")); tipConfiguration.setBaseAmount(new BigInteger("1000")); tipConfiguration.setEnterAmountEnabled(true); tipConfiguration.setFooter("Thank you"); @@ -87,21 +87,23 @@ A [sale](#2) operation which also returns a card token. (not available for all a ```java //Initiate a sale for 10.00 in Great British Pounds -api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); -//Initiate a sale for 10.00 in Great British Pounds with tipping configuration -//This feature is not available for HiLite & Hi5 devices +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices TipConfiguration tipConfiguration = new TipConfiguration(); tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); -tipConfiguration.setAmount(new BigInteger("1000")); +tipConfiguration.setTipAmount(new BigInteger("1000")); tipConfiguration.setBaseAmount(new BigInteger("1000")); tipConfiguration.setEnterAmountEnabled(true); tipConfiguration.setFooter("Thank you"); tipConfiguration.setSkipEnabled(true); SaleOptions options = new SaleOptions(); options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); -api.saleAndTokenizeCard(new BigInteger("1000"),Currency.GBP,options); +api.sale(new BigInteger("1000"),Currency.GBP,options); ``` **Events invoked** From af280b29cf0becf1658e42a553216a40bd55ca74 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 25 Nov 2022 13:17:09 +0100 Subject: [PATCH 028/115] add: Android SDK v7.0.1 (#40) --- android/androidreleasenotes.md | 2 +- android/androidtransactions.md | 1 - .../androidreleasenotes.md | 2 +- .../androidtransactions.md | 1 - .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 368 ++++++ .../androideventlisteners.md | 700 ++++++++++++ .../androideventsubscribers.md | 73 ++ .../androidintegrationguide.md | 542 +++++++++ .../androidintroduction.md | 148 +++ .../androidmigrationguide.md | 259 +++++ .../androidobjects.md | 1011 +++++++++++++++++ .../androidreleasenotes.md | 214 ++++ .../androidtransactions.md | 579 ++++++++++ .../version-Android SDK 7.0.1-sidebars.json | 8 + android_versions.json | 1 + 16 files changed, 3927 insertions(+), 4 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.0.1-sidebars.json diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index b282f04..2972937 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,7 +11,7 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: -## 7.0.0 +## 7.0.1 - Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) - All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 6ecf95a..54f7a07 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -70,7 +70,6 @@ Invoked when the terminal finishes processing the transaction. ## Sale And Tokenize Card{#3} -`saleAndTokenizeCard` A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md index bc93474..2c580dc 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md @@ -11,7 +11,7 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: -## 7.0.0 +## 7.0.1 - Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-interfaces) - All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md index f2a8fbc..b3de019 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md @@ -70,7 +70,6 @@ Invoked when the terminal finishes processing the transaction. ## Sale And Tokenize Card{#3} -`saleAndTokenizeCard` A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.0.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md new file mode 100644 index 0000000..af0bcb8 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md @@ -0,0 +1,368 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.0.1/androideventlisteners.md new file mode 100644 index 0000000..93ffb87 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androideventlisteners.md @@ -0,0 +1,700 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { + // Notify the app user transaction has been started ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.0.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md new file mode 100644 index 0000000..b6138e7 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md @@ -0,0 +1,542 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue + // For this sample app we are not going to implement this event + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:6.x.x' + + //Handpoint Staging/Development SDK (Debug devices) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +```groovy +allprojects { //Handpoint Staging/Development SDK + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") + credentials { + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md new file mode 100644 index 0000000..92c9ef2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md @@ -0,0 +1,148 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +### Gradle Settings + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md new file mode 100644 index 0000000..4a88c63 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md @@ -0,0 +1,259 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md new file mode 100644 index 0000000..b8f5a96 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md @@ -0,0 +1,1011 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMerchantId(mid); +//Optionally +credential1.setTerminalId(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMerchantId(mid); +//Optionally +credential.setTerminalId(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md new file mode 100644 index 0000000..2972937 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md @@ -0,0 +1,214 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md new file mode 100644 index 0000000..54f7a07 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md @@ -0,0 +1,579 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.0.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.0.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.0.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index b95bf3f..59e99df 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.0.1", "Android SDK 7.0.0", "Android SDK 6.7.4", "Android SDK 6.7.2" From f63a7ca1bdd63a21986ae4441c8f9b0dde161ec3 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 5 Dec 2022 15:05:38 +0100 Subject: [PATCH 029/115] Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide --- android/androidmigrationguide.md | 12 ++- android/androidobjects.md | 86 +++++++++++++++-- android/androidtransactions.md | 2 +- .../androidmigrationguide.md | 10 +- .../androidobjects.md | 85 +++++++++++++++-- .../androidtransactions.md | 2 +- .../androidmigrationguide.md | 11 ++- .../androidobjects.md | 94 +++++++++++++++++-- .../androidtransactions.md | 3 +- 9 files changed, 263 insertions(+), 42 deletions(-) diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 4a88c63..7ce6091 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -12,7 +12,9 @@ The new version 7.X.X of our Android SDK introduces the following changes: 2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). -4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + ## 1. New Interfaces @@ -225,7 +227,6 @@ class KotlinClient: Events.PosRequired { The methods affected by this change are the following: - [Sale](androidtransactions.md#2) -- [Sale and Tokenize](androidtransactions.md#3) - [SaleReversal](androidtransactions.md#4) - [Refund](androidtransactions.md#5) - [RefundReversal](androidtransactions.md#6) @@ -256,4 +257,9 @@ You can disable the duplicate check functionality for the following financial op ## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` - Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. \ No newline at end of file diff --git a/android/androidobjects.md b/android/androidobjects.md index b8f5a96..a6c2ac8 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -530,9 +530,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); ``` @@ -561,9 +561,9 @@ Credential credential1 = new Credential(); //Optionally credential1.setAcquirer(YOUR_ACQUIRER); //Optionally -credential1.setMerchantId(mid); +credential1.setMid(mid); //Optionally -credential1.setTerminalId(tid); +credential1.setTid(tid); //Optionally credential1.setMcc(mcc); @@ -599,9 +599,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -754,9 +754,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -826,9 +826,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -861,6 +861,72 @@ options.setTipConfiguration(config); options.setTipConfiguration(new TipConfiguration(AMOUNT)); ``` +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + ## Settings {#settings} `Settings` Object diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 54f7a07..596ba70 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -80,7 +80,7 @@ A [sale](#2) operation which also returns a card token. (not available for all a | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md index b6a6fb7..ffdaf32 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidmigrationguide.md @@ -12,7 +12,8 @@ The new version 7.X.X of our Android SDK introduces the following changes: 2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). -4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. ## 1. New Interfaces @@ -225,7 +226,6 @@ class KotlinClient: Events.PosRequired { The methods affected by this change are the following: - [Sale](androidtransactions.md#2) -- [Sale and Tokenize](androidtransactions.md#3) - [SaleReversal](androidtransactions.md#4) - [Refund](androidtransactions.md#5) - [RefundReversal](androidtransactions.md#6) @@ -256,4 +256,8 @@ You can disable the duplicate check functionality for the following financial op ## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` - Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md index b8f5a96..b30abe6 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md @@ -530,9 +530,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); ``` @@ -561,9 +561,9 @@ Credential credential1 = new Credential(); //Optionally credential1.setAcquirer(YOUR_ACQUIRER); //Optionally -credential1.setMerchantId(mid); +credential1.setMid(mid); //Optionally -credential1.setTerminalId(tid); +credential1.setTid(tid); //Optionally credential1.setMcc(mcc); @@ -599,9 +599,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -754,9 +754,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -826,9 +826,9 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -860,6 +860,71 @@ options.setTipConfiguration(config); //Alternatively, you can set the tip amount directly options.setTipConfiguration(new TipConfiguration(AMOUNT)); ``` +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + ## Settings {#settings} diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md index b3de019..b446100 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidtransactions.md @@ -80,7 +80,7 @@ A [sale](#2) operation which also returns a card token. (not available for all a | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md index 4a88c63..7f4bb77 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidmigrationguide.md @@ -12,7 +12,8 @@ The new version 7.X.X of our Android SDK introduces the following changes: 2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). -4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. ## 1. New Interfaces @@ -225,7 +226,6 @@ class KotlinClient: Events.PosRequired { The methods affected by this change are the following: - [Sale](androidtransactions.md#2) -- [Sale and Tokenize](androidtransactions.md#3) - [SaleReversal](androidtransactions.md#4) - [Refund](androidtransactions.md#5) - [RefundReversal](androidtransactions.md#6) @@ -256,4 +256,9 @@ You can disable the duplicate check functionality for the following financial op ## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` - Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. \ No newline at end of file + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + ## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + + Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md index b8f5a96..862459a 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md @@ -530,9 +530,11 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); + +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); + //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); ``` @@ -561,9 +563,9 @@ Credential credential1 = new Credential(); //Optionally credential1.setAcquirer(YOUR_ACQUIRER); //Optionally -credential1.setMerchantId(mid); +credential1.setMid(mid); //Optionally -credential1.setTerminalId(tid); +credential1.setTid(tid); //Optionally credential1.setMcc(mcc); @@ -599,9 +601,10 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); + //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -754,9 +757,10 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); + //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -826,9 +830,77 @@ Credential credential = new Credential(); //Optionally credential.setAcquirer(YOUR_ACQUIRER); //Optionally -credential.setMerchantId(mid); + +credential.setMid(mid); +//Optionally +credential.setTid(tid); + +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); //Optionally -credential.setTerminalId(tid); +credential.setTid(tid); //Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). auth.add(credential); options.setMerchantAuth(auth); @@ -861,6 +933,8 @@ options.setTipConfiguration(config); options.setTipConfiguration(new TipConfiguration(AMOUNT)); ``` + + ## Settings {#settings} `Settings` Object diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md index 54f7a07..0f4aa85 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidtransactions.md @@ -80,7 +80,8 @@ A [sale](#2) operation which also returns a card token. (not available for all a | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + **Code example** From c4ca3a329ca1dbf489a2099885bcc00ca30893a3 Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Tue, 20 Dec 2022 17:32:06 +0100 Subject: [PATCH 030/115] feat: italian lang support (#43) --- android/androiddevicemanagement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index af0bcb8..555be6e 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -254,7 +254,7 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT.| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT.| **Code example** From 4a03ba24e27cc5fa347506b9ffb7a83f6df59345 Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Tue, 20 Dec 2022 17:34:46 +0100 Subject: [PATCH 031/115] feat: italian lang support (#44) --- android/androidobjects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index a6c2ac8..9bba1f5 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -993,7 +993,7 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` ## Tender Type{#36} From 464158f445e37b39c36d97166f78efeab0095250 Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:23:48 +0100 Subject: [PATCH 032/115] feat: Norweian (#45) --- android/androiddevicemanagement.md | 2 +- android/androidobjects.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index 555be6e..5f0850d 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -254,7 +254,7 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT.| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| **Code example** diff --git a/android/androidobjects.md b/android/androidobjects.md index 9bba1f5..bf42005 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -993,7 +993,7 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` ## Tender Type{#36} From b82af20ac0938c095891f7ee1d7efae8fff2cf54 Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Mon, 9 Jan 2023 16:38:34 +0100 Subject: [PATCH 033/115] feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine --- restapi/restendpoints.md | 55 ++++++++++++++++++++++++++++++++++++++++ restapi/restobjects.md | 19 ++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 5056f71..85c923e 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -251,6 +251,61 @@ RESPONSE: `customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. ::: +## /transaction-result/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "currency": "EUR", + "amount": 1000 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using wrong currency): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Wrong currency [EU]" + } +} +``` + ## Transaction Result Recovery diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 7e2e3a3..9ffe076 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -614,3 +614,22 @@ An enum representing different tender types. Possible values `NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Amount of the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `currency`
*String* |The currency of the tip | + +**Code example** + +````json +{ + "currency": "EUR", + "amount": 1000 +} +```` From 4a91400860daffbc6351cfb26193f8c34f9bbcfa Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:37:50 +0100 Subject: [PATCH 034/115] fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine --- restapi/restendpoints.md | 13 +++++++------ restapi/restobjects.md | 10 ++++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 85c923e..6c9b4ca 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -251,14 +251,16 @@ RESPONSE: `customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. ::: -## /transaction-result/{guid}/tip-adjustment +## /transactions/{guid}/tip-adjustment `TipAdjustment` POST endpoint used to execute a tip adjustment operation. -A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. **Parameters** @@ -287,8 +289,7 @@ REQUEST: --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ --header 'Content-Type: application/json' \ --data-raw '{ - "currency": "EUR", - "amount": 1000 + "amount": 5.25 }' RESPONSE code 200: @@ -296,12 +297,12 @@ RESPONSE code 200: "statusMessage": "tip adjusted" } -Error example response (using wrong currency): +Error example response (using invalid guid): { "error": { "statusCode": 400, "name": "BadRequestError", - "message": "Wrong currency [EU]" + "message": "Invalid guid [fake-guid]" } } ``` diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 9ffe076..d8fef68 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -622,14 +622,16 @@ Possible values | Property | Description | | ----------- | ----------- | -| `amount`
*Biginteger* | Amount of the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | -| `currency`
*String* |The currency of the tip | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | **Code example** ````json { - "currency": "EUR", - "amount": 1000 + "amount": 10.25 +} + +{ + "amount": 20 } ```` From 0beb9809509787ff3308f63dddccfd83111a9b46 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 10 Jan 2023 12:37:17 +0100 Subject: [PATCH 035/115] New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment --- android/androidreleasenotes.md | 11 + .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 368 ++++++ .../androideventlisteners.md | 700 +++++++++++ .../androideventsubscribers.md | 73 ++ .../androidintegrationguide.md | 542 +++++++++ .../androidintroduction.md | 148 +++ .../androidmigrationguide.md | 265 ++++ .../androidobjects.md | 1077 +++++++++++++++++ .../androidreleasenotes.md | 224 ++++ .../androidtransactions.md | 581 +++++++++ .../version-Android SDK 7.0.2-sidebars.json | 8 + android_versions.json | 1 + restapi/restreleasenotes.md | 8 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.12.0/restdownloads.md | 10 + .../version-REST API 2.12.0/restendpoints.md | 329 +++++ .../restintroduction.md | 50 + .../version-REST API 2.12.0/restobjects.md | 637 ++++++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 46 + .../version-REST API 2.12.0/restsandbox.md | 44 + .../version-REST API 2.12.0-sidebars.json | 8 + restapi_versions.json | 1 + .../Handpoint_API_REST_Collection.json.zip | Bin 1667 -> 1757 bytes 25 files changed, 5175 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.0.2/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.0.2-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.12.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.12.0-sidebars.json diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 2972937..81cc38d 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,17 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + ## 7.0.1 - Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.0.2/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md new file mode 100644 index 0000000..5f0850d --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md @@ -0,0 +1,368 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.0.2/androideventlisteners.md new file mode 100644 index 0000000..93ffb87 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androideventlisteners.md @@ -0,0 +1,700 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { + // Notify the app user transaction has been started ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.0.2/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md new file mode 100644 index 0000000..b6138e7 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md @@ -0,0 +1,542 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue + // For this sample app we are not going to implement this event + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your main **``**: + +```groovy +android:launchMode="singleTask" +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:6.x.x' + + //Handpoint Staging/Development SDK (Debug devices) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +```groovy +allprojects { //Handpoint Staging/Development SDK + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") + credentials { + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10 pounds + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md new file mode 100644 index 0000000..92c9ef2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md @@ -0,0 +1,148 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +### Gradle Settings + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:6.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [6.0.0,7.0.0) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.0.2/androidmigrationguide.md new file mode 100644 index 0000000..6d0b68f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md new file mode 100644 index 0000000..bf42005 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md @@ -0,0 +1,1077 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md new file mode 100644 index 0000000..63837ae --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md @@ -0,0 +1,224 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.0.2 +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.0.2/androidtransactions.md new file mode 100644 index 0000000..75f6678 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidtransactions.md @@ -0,0 +1,581 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.0.2-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.0.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.0.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 59e99df..c23190f 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.0.2", "Android SDK 7.0.1", "Android SDK 7.0.0", "Android SDK 6.7.4", diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 92aa143..58acd2e 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,14 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + ## 2.10.0 **Features:** diff --git a/restapi_versioned_docs/version-REST API 2.12.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.12.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md new file mode 100644 index 0000000..b904728 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. + +[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.12.0/restendpoints.md new file mode 100644 index 0000000..6c9b4ca --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restendpoints.md @@ -0,0 +1,329 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md new file mode 100644 index 0000000..91afd98 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md new file mode 100644 index 0000000..d8fef68 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -0,0 +1,637 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": false +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": false +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} + +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.12.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md new file mode 100644 index 0000000..58acd2e --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md @@ -0,0 +1,46 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.12.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.12.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.12.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.12.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.12.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index e8d2ef4..25ee2b5 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.12.0", "REST API 2.10.0", "REST API 2.7.1", "REST API 2.6.0" diff --git a/static/files/Handpoint_API_REST_Collection.json.zip b/static/files/Handpoint_API_REST_Collection.json.zip index 13a8c4618b0ce0952240dcbb9e46a06c129b3166..e06a18ce31c8f8cf2fd0be67bab30a244c5ded34 100644 GIT binary patch literal 1757 zcmcJPc{J2}7{-5N7eYytD})-^O7`U-Mb|b>mKk(sm>gSX?6SpA$Wn|g8e`2CNnF`Q zwqzL*qH%AywwM{q*b>*BIp=n6=idJ7+~+;-Iq&zc_kEu4IUkrQE1M9&#VALVoDJ}| z7R~{H3LpWPIAU*l;oPu(5(coV67b8{tt5<`Z@C3H`vfU^;e7o(9kD13?$#}5jGr40 ztLW~F!&+PM0i0V#EtnlfZ!_BeHV*({+k^lBV-WyQ?L2Wa8Ulavwo3Ib!~~jqqFjO`+(C6OqtnKL&R8JgRgM`Z- z7)!loRzF7Dt}zJI7{<1}GDVjQEZXyUB}XZ0Z0{}mXo^8~S(1d6kRu8Q8&IhIh|tSB`2FtfTxn+1(IH4qi?p#C4m_beH{C=F)J=Of z`aa2I-waV-rJt$qshX4@?&P^tCvvEy@^KKv7yeGlL=4&|IF=^t9cxYW>b?h6!WLtt zdCK%gMBX@=g8lvRQsdBMo0Mt^Lt*tl$D=y8&#o2mh!}aIgZ9{8=XT~Jnoi>&P(9-DR#&#&D-BXQOoUQ?$W`y2=l8`qzEX{=Wd0cdq<^c z{jnWlV;hGuCx?+@NX7j!HID~<@*vUYbzHQDZ!(>G1V30$&yP_GO?#s}I~=j9+$D#UML<$TTi`Ra+g=<| zc5_i$Qu!AhLA4Y;(?)#rD#g(@YrLvSD|Vt)b7FnT->RBVU(CozI81sdI7-ExQ%coF zo3Q1Z=RkRpI%U_LeSTTU;>(HYMB}!8pM%tRd#>Kq$CLE4Zx(a1k<#hZmMmg#Na>`p zScb?3aUJPvy~itl9v*@?nriuzWoCHfJZvGUSV9S6YTef&9F}Vgr8Z zI^nIa4mFyh^<i_N%5inI`LsA z`D?Ohxh)pk`teoc)rjRh@~5rc)1Er@;Rz3p{Ocikj>@l=@c0IKSqm z){<2Q3ET_%+?~B*Q5n`rR|$`#QlhI|YN)vd#CrWZ18c*YgB0@{i>{;a3O&i!{aMxh zR(}LcHk}tPh|Fk+W$o>pPW{zg#hW~0l|NDY`8Om&C~q?yX3EJmsybK#V*>ytwqV}{ z+9ZQKdJLeUQ04}gEUzP!6j49Qw*CLI4TC<0aX~wwSIy0AR{3pWVG%5N5!N#TCn0Nc z5*%wQ$^z_SmkcBG%P5;=Jca(zeDnWAMovQ g%&fnv5FBFs&HtM`%#@vjxsQcWd=LO=WM{tq0?f_>2mk;8 literal 1667 zcmWIWW@Zs#-~dAZ?z15bP>`s}z@WsSz~GUXmr{_QnO73;7~mNnAi75veEKiTfYVAhg^rUIdM|P!c?uHMe(l1;;bFW~@-G=7r2f`LE%GW*M8dQ34=kxe* zt%n{z1uM2x++39RRDb@YE>~H0oxY>Ter;ZRFLu(%hvRMBR-v?-GRCBTUYt+ zjfjXp!CO>t^uykOsk43NycIrUSoC54f;S>1{egZ*g_zx*-)Pj|;Na~ODI&WtAzA)x zOT(?zjNBY*{Z7Xs8G`ok^&0%JW|*%&IpzWPDw*H6q+7K`zpyGuM?48r{N%$mFF`fb zT5ex!==VOhG85Mm(@t56`pV+sEHO%Y#4L zN!{f)K?2WFD?#UpZ29DK`AjxA*K4{V`|P0iPMn z%u3VuhWTBM`uZ$2Ow#fkPo#hHGnHxE*|x_n^A~uxDlFe5I`{FXtVQZvubE#y;1QHx z`F!gC$eNs=1q_PLPimN?K1r6_W&BWbo5|&@$IHR*y=Io`L9Q8VUQ8AGe(aef!`4%c zR!RZ0J~&99oS_=)QTO4^!qv`iEMj7hytyy4?avo0tsJ$E?v53U`dQZcTP!Y9@Jimg zIMbf}$)go>S+Zvq9J``v`!;$>xebHy>Ay-{(Na?$y6=1*7<94Ldb7u>TffaMPgMuV zDX8VwKH?DG9Z{!qX?NcJ=M0}-Gnn^GEBv=S_1-KwZbQL;4L5$~=GzDRxV}{BJGzI} zR(yrsQcm0Bx8ppndz#K)?t0UDw|A-5v80QMcG;ELKVOA2sM*KPOkn(0aW81!M_C6p z?XIgI1%BI^ZJm8@{@=X!4o4#1MCM$5Q(FD^pojGA^8AY$S9j0dy<30oySIFQ|6Hgx z5BzxA%6H$|)19~cMe6^aefGX63BXzci2w@_U0?|mAMfkv>>nJVuNO~ZVU$~dQ5YpBh$g2eBqehyaQWOgtKwk7-P|(A z>F=D)`($Fd&+fZ3WtZQQ>Whp(|FUxg=y2P%0!v4bF9W<8nM9ZoWiWEsfXZMPSkee$ qkr)VAN@R5Vklg|baTr+A*aVCrs)m1nH!B;+cqSlx4Wye`K|BDLwyP`v From 39081781ab1539389b67357c609b59d8c80afeb1 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 13 Jan 2023 17:53:54 +0100 Subject: [PATCH 036/115] Fix: Error Invalid URL's (#50) --- docs/intro.md | 2 +- restapi/restintroduction.md | 2 +- .../version-REST API 2.10.0/restintroduction.md | 2 +- .../version-REST API 2.12.0/restintroduction.md | 2 +- restapi_versioned_docs/version-REST API 2.6.0/restoverview.md | 2 +- .../version-REST API 2.7.1/restintroduction.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/intro.md b/docs/intro.md index b2b6a69..873ce85 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -48,7 +48,7 @@ The following flow shows the interactions between your application and the Handp :::caution -**4.2)** **IMPORTANT** Feature only compatible with Handpoint App v3.3.0 and above. In case the original transaction request does not ontain a callbackUrl and token, the transaction result is sent back from the terminal to Handpoint's REST-API. The result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the answer from the initial POST[1] to the REST-API (see step **2**)). +**4.2)** **IMPORTANT** Feature only compatible with Handpoint App v3.3.0 and above. In case the original transaction request does not ontain a callbackUrl and token, the transaction result is sent back from the terminal to Handpoint's REST-API. The result can then be retrieved from the endpoint GET where the transactionResultId (also called cloud transaction identifier) is found in the answer from the initial POST[1] to the REST-API (see step **2**)). ::: diff --git a/restapi/restintroduction.md b/restapi/restintroduction.md index 91afd98..4ca8dfd 100644 --- a/restapi/restintroduction.md +++ b/restapi/restintroduction.md @@ -40,7 +40,7 @@ The following flow shows the interactions between your application and the Handp **4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. - **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md index 91afd98..4ca8dfd 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restintroduction.md @@ -40,7 +40,7 @@ The following flow shows the interactions between your application and the Handp **4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. - **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md index 91afd98..4ca8dfd 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restintroduction.md @@ -40,7 +40,7 @@ The following flow shows the interactions between your application and the Handp **4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. - **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restoverview.md b/restapi_versioned_docs/version-REST API 2.6.0/restoverview.md index 7185875..5995ed7 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restoverview.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restoverview.md @@ -29,7 +29,7 @@ The following flow shows the interactions between your application and the Handp :::caution -**4.2)** **IMPORTANT** Feature only compatible with Handpoint App v3.3.0 and above. In case the original [transaction request](restobjects.md#transaction-request-object) does not ontain a callbackUrl and token, the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the answer from the initial POST[1] to the REST-API (see step **2**)). +**4.2)** **IMPORTANT** Feature only compatible with Handpoint App v3.3.0 and above. In case the original [transaction request](restobjects.md#transaction-request-object) does not ontain a callbackUrl and token, the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the answer from the initial POST[1] to the REST-API (see step **2**)). ::: diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restintroduction.md b/restapi_versioned_docs/version-REST API 2.7.1/restintroduction.md index 91afd98..4ca8dfd 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restintroduction.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restintroduction.md @@ -40,7 +40,7 @@ The following flow shows the interactions between your application and the Handp **4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. - **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET https://cloud.handpoint.[com//io]/transaction-result/{transactionResultId} where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. From a36257720b86f9e97aa820239c85e9b4774a5950 Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Wed, 18 Jan 2023 11:59:36 +0100 Subject: [PATCH 037/115] fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error --- javascript/javascriptintroduction.md | 4 ++-- javascript/javascriptreleasenotes.md | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index 2b68489..2c3a6bb 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 2ba0e6b..24edd58 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -10,6 +10,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: +## 6.2.1 + +**Fixes**: +- Reconnection management + ## 6.2.0 **Features**: From 6d2ac49de9c1979d4aa9294c8a5ab5aef6e23c26 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 23 Jan 2023 13:20:43 +0100 Subject: [PATCH 038/115] add: JS SDK v6.2.1 (#52) --- javascript/javascriptreleasenotes.md | 2 +- .../javascriptintroduction.md | 39 ++ .../javascriptobjects.md | 623 ++++++++++++++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 92 +++ .../javascriptreleasenotes.md | 44 ++ .../javascriptsandbox.md | 45 ++ .../javascriptterminalmanagement.md | 220 +++++++ .../javascripttransactiontypes.md | 447 +++++++++++++ .../javascriptintroduction.md | 4 +- ...version-JavaScript SDK 6.2.1-sidebars.json | 8 + javascript_versions.json | 3 +- 12 files changed, 1546 insertions(+), 4 deletions(-) create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 6.2.1-sidebars.json diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 24edd58..f1e51ab 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -13,7 +13,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 6.2.1 **Fixes**: -- Reconnection management +- Reconnection management. ## 6.2.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptintroduction.md new file mode 100644 index 0000000..2c3a6bb --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md new file mode 100644 index 0000000..3380930 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md @@ -0,0 +1,623 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference" +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptquickintegration.md new file mode 100644 index 0000000..f3e18ce --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptquickintegration.md @@ -0,0 +1,92 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example 0821032395-PAXA920. If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable environmentIsDevelopment to true otherwise change it to false. + +4)Open the html file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md new file mode 100644 index 0000000..f1e51ab --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptterminalmanagement.md new file mode 100644 index 0000000..b6241c0 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptterminalmanagement.md @@ -0,0 +1,220 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascripttransactiontypes.md new file mode 100644 index 0000000..9a7d0c4 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascripttransactiontypes.md @@ -0,0 +1,447 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleAndTokenization('1000', 'USD', saleOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale and Tokenization Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +Handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction Status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md index 2b68489..2c3a6bb 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 6.2.1-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 6.2.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 6.2.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 5b5ef55..407b39f 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,5 +1,6 @@ [ - "Javascript SDK 6.2.0", + "JavaScript SDK 6.2.1", + "JavaScript SDK 6.2.0", "JavaScript SDK 6.1.0", "JavaScript SDK 6.0.1" ] From bc93fc78c44ec7710809ea5fcc4731f7a8affa0d Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 23 Jan 2023 13:27:20 +0100 Subject: [PATCH 039/115] New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name --- javascript_versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript_versions.json b/javascript_versions.json index 407b39f..9563bfa 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,6 +1,6 @@ [ "JavaScript SDK 6.2.1", - "JavaScript SDK 6.2.0", + "Javascript SDK 6.2.0", "JavaScript SDK 6.1.0", "JavaScript SDK 6.0.1" ] From 09b28b02b7a3337cbd48fb960beaca26a036b9ba Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:15:21 +0100 Subject: [PATCH 040/115] feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine --- android/androidobjects.md | 54 +++++++++++++++++++ android/androidtransactions.md | 4 ++ javascript/javascriptobjects.md | 66 +++++++++++++++++++++++- javascript/javascripttransactiontypes.md | 7 +++ restapi/restobjects.md | 57 +++++++++++++++++++- windows/windowsobjects.md | 43 +++++++++++++++ windows/windowstransactions.md | 1 + 7 files changed, 229 insertions(+), 3 deletions(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index bf42005..a45df6a 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -51,6 +51,7 @@ An object holding information about the result of a transaction. | `merchantAddress`
*String* | Merchant Address.| | `merchantName`
*String* | Merchant Name.| | `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `mid`
*String* | Merchant Identifier.| | `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| | `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| @@ -114,6 +115,13 @@ An object holding information about the result of a transaction. "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", "merchantName": "Hago la cama", "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, "mid": "", "originalEFTTransactionID": "", "paymentScenario": "CHIPCONTACTLESS", @@ -684,6 +692,7 @@ An object to store customer reference options for regular operations. | Parameter | Description | | ----------- | ----------- | | `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** @@ -692,6 +701,10 @@ Options options = new Options(); //If you use a customer reference options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); ``` ## Payment Scenario{#35} @@ -739,6 +752,7 @@ An object to store all the customization options for a refund. | `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** @@ -766,6 +780,10 @@ options.setPinBypass(true); //If you need to disable the duplicate payment check service options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); ``` ## Report Configuration{#19} @@ -811,6 +829,7 @@ An object to store all the customization options for a sale. | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** @@ -859,6 +878,10 @@ options.setTipConfiguration(config); //Alternatively, you can set the tip amount directly options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); ``` ## Sale and Tokenize Options @@ -1075,3 +1098,34 @@ An enum representing different verification methods used in the transaction. **Possible values** `UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 75f6678..fdfbc38 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -38,8 +38,12 @@ tipConfiguration.setBaseAmount(new BigInteger("1000")); tipConfiguration.setEnterAmountEnabled(true); tipConfiguration.setFooter("Thank you"); tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + SaleOptions options = new SaleOptions(); options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); api.sale(new BigInteger("1000"),Currency.GBP, options); ``` diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 3380930..1d69642 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -48,6 +48,7 @@ An object holding information about the result of a transaction. | `merchantAddress`
*String * | Merchant Address| | `merchantName`
*String * | Merchant Name| | `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `mid`
*String * | Merchant Identifier| | `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| | `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| @@ -109,6 +110,13 @@ An object holding information about the result of a transaction. "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", "merchantName": "Hago la cama", "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, "mid": "", "originalEFTTransactionID": "", "paymentScenario": "CHIPCONTACTLESS", @@ -246,12 +254,20 @@ An object to store all the customisation options for an operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** ```json { - "customerReference": "MyCustomReference" + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ``` @@ -271,6 +287,7 @@ An object to store the customization options for a sale operation. This object c | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** @@ -301,6 +318,13 @@ An object to store the customization options for a sale operation. This object c "mcc": "33333" } ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ``` @@ -320,6 +344,9 @@ An object to store the customization options for a refund. This object can be em | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| + +**Code example** ```json { @@ -348,6 +375,13 @@ An object to store the customization options for a refund. This object can be em "mcc": "33333" } ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ``` @@ -621,3 +655,33 @@ An enum representing different types of transactions. **Possible values** `UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` \ No newline at end of file diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 9a7d0c4..8b66b3e 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -49,6 +49,13 @@ var saleOptions = { mcc: "33333" } ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } } Handpoint.sale('1000', 'USD', saleOptions, function (stat) { diff --git a/restapi/restobjects.md b/restapi/restobjects.md index d8fef68..fa77a65 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -109,6 +109,7 @@ An object holding information about the result of a transaction. | `merchantAddress`
*String * | Merchant Address| | `merchantName`
*String * | Merchant Name| | `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `mid`
*String * | Merchant Identifier| | `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| | `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| @@ -170,6 +171,13 @@ An object holding information about the result of a transaction. "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", "merchantName": "Hago la cama", "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, "mid": "", "originalEFTTransactionID": "", "paymentScenario": "CHIPCONTACTLESS", @@ -222,6 +230,7 @@ An object to store information about the request sent to the payment terminal. | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| **Code example** @@ -254,7 +263,14 @@ An object to store information about the request sent to the payment terminal. "mcc": "3333", "externalId": "4444" }], - "duplicate_check": false + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } // Result will be served back to Handpoint's REST-API @@ -283,7 +299,14 @@ An object to store information about the request sent to the payment terminal. "mcc": "3333", "externalId": "4444" }], - "duplicate_check": false + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ```` @@ -635,3 +658,33 @@ Possible values "amount": 20 } ```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index b2dd3a7..ce54e3e 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -48,6 +48,7 @@ An object holding information about the result of a transaction. | `merchantAddress`
*String* | Merchant Address| | `merchantName`
*String* | Merchant Name| | `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| | `mid`
*String* | Merchant Identifier| | `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| | `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| @@ -106,6 +107,13 @@ An object holding information about the result of a transaction. "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", "merchantName": "Hago la cama", "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, "mid": "", "originalEFTTransactionID": "", "paymentScenario": "CHIPCONTACTLESS", @@ -401,6 +409,11 @@ A class containing optional transaction parameters now supported by the device. |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| |`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```| ## Log Level{#9} @@ -512,3 +525,33 @@ bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); //Check the current logLevel LogLevel level = HapiManager.GetLogLevel(); ``` + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index b0c7281..4b42a92 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -34,6 +34,7 @@ this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); // With options Dictionary map = new Dictionary(); map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); ``` From 5b032599f91ced0b21eba34e5e67d400002520dd Mon Sep 17 00:00:00 2001 From: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Date: Thu, 2 Feb 2023 11:23:59 +0100 Subject: [PATCH 041/115] fix: Valid characters for Metadata (#56) --- android/androidobjects.md | 16 ++++++++-------- javascript/javascriptobjects.md | 16 ++++++++-------- restapi/restobjects.md | 12 ++++++------ windows/windowsobjects.md | 20 ++++++++++---------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index a45df6a..5bfa2ff 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -692,7 +692,7 @@ An object to store customer reference options for regular operations. | Parameter | Description | | ----------- | ----------- | | `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| -| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | **Code example** @@ -752,7 +752,7 @@ An object to store all the customization options for a refund. | `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| -| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -829,7 +829,7 @@ An object to store all the customization options for a sale. | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| -| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -1109,11 +1109,11 @@ An object to store metadata. This field can be used to pass custom data to the H | Property | Description | | ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 1d69642..067a170 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -254,7 +254,7 @@ An object to store all the customisation options for an operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -287,7 +287,7 @@ An object to store the customization options for a sale operation. This object c | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -344,7 +344,7 @@ An object to store the customization options for a refund. This object can be em | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -666,11 +666,11 @@ An object to store metadata. | Property | Description | | ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index fa77a65..0694760 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -230,7 +230,7 @@ An object to store information about the request sent to the payment terminal. | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** @@ -669,11 +669,11 @@ An object to store metadata. | Property | Description | | ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index ce54e3e..60b7127 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -409,11 +409,11 @@ A class containing optional transaction parameters now supported by the device. |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| |`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| -| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```| -| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```| -| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```| -| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```| -| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| ## Log Level{#9} @@ -536,11 +536,11 @@ Object used to echo metadata1-5, in the transaction result, if it was set as an | Property | Description | | ----------- | ----------- | -| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters| -| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters| +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** From 61fec4a54af9deeefe9a44e482e9e16a4ba35a36 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 20 Feb 2023 10:19:10 +0100 Subject: [PATCH 042/115] Added new Android integration info (#57) --- android/androidintegrationguide.md | 79 ++++++++++------- .../androidintegrationguide.md | 82 +++++++++++------- .../androidintegrationguide.md | 84 +++++++++++-------- .../androidintegrationguide.md | 83 ++++++++++-------- 4 files changed, 199 insertions(+), 129 deletions(-) diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index b6138e7..4f6ac87 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -30,10 +30,27 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2. SDK distribution** @@ -52,7 +69,7 @@ The latest version is compiled with java **1.8** For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -69,7 +86,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -198,7 +215,7 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds // Use the currency of the country in which you will be deploying terminals } @@ -245,6 +262,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren options.setBudgetNumber("YOUR_BUDGET_NUMBER"); return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override @@ -302,10 +321,27 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2.1 In the gradle.build (app module)** @@ -334,10 +370,7 @@ android { dependencies { //Handpoint Production SDK (Production devices) - implementation 'com.handpoint.api:sdk:6.x.x' - - //Handpoint Staging/Development SDK (Debug devices) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x' } ``` @@ -354,23 +387,6 @@ allprojects { //Handpoint Production SDK } ``` -```groovy -allprojects { //Handpoint Staging/Development SDK - repositories { - google() - mavenCentral() - maven { - name = "Handpoint Nexus" - url = uri("urlProvided") - credentials { - username = 'usernameProvided' - password = 'passwordProvided' - } - } - } -} -``` - :::tip During the build process, a DEX error may appear. @@ -483,7 +499,8 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md index b6138e7..696982d 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md @@ -30,10 +30,27 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2. SDK distribution** @@ -52,7 +69,7 @@ The latest version is compiled with java **1.8** For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -69,7 +86,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -198,7 +215,7 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds // Use the currency of the country in which you will be deploying terminals } @@ -245,6 +262,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren options.setBudgetNumber("YOUR_BUDGET_NUMBER"); return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override @@ -302,10 +321,28 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: -```groovy -android:launchMode="singleTask" +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2.1 In the gradle.build (app module)** @@ -313,7 +350,7 @@ android:launchMode="singleTask" ```groovy android { defaultConfig { - minSdkVersion 22 //Required to support all PAX & Telpo models + minSdkVersion 22 //Required to support all devices targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true @@ -334,10 +371,7 @@ android { dependencies { //Handpoint Production SDK (Production devices) - implementation 'com.handpoint.api:sdk:6.x.x' - - //Handpoint Staging/Development SDK (Debug devices) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x' } ``` @@ -354,23 +388,6 @@ allprojects { //Handpoint Production SDK } ``` -```groovy -allprojects { //Handpoint Staging/Development SDK - repositories { - google() - mavenCentral() - maven { - name = "Handpoint Nexus" - url = uri("urlProvided") - credentials { - username = 'usernameProvided' - password = 'passwordProvided' - } - } - } -} -``` - :::tip During the build process, a DEX error may appear. @@ -483,7 +500,8 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md index b6138e7..7cf6090 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md @@ -23,17 +23,34 @@ The new generation of Handpoint SDK's is designed to make your life easier. Simp At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. :::warning -Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method. ::: **Let's start programming!** **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2. SDK distribution** @@ -52,7 +69,7 @@ The latest version is compiled with java **1.8** For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -69,7 +86,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -198,7 +215,7 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds // Use the currency of the country in which you will be deploying terminals } @@ -245,6 +262,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren options.setBudgetNumber("YOUR_BUDGET_NUMBER"); return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override @@ -302,10 +321,28 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: -```groovy -android:launchMode="singleTask" +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2.1 In the gradle.build (app module)** @@ -313,7 +350,7 @@ android:launchMode="singleTask" ```groovy android { defaultConfig { - minSdkVersion 22 //Required to support all PAX & Telpo models + minSdkVersion 22 //Required to support all devices targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true @@ -334,10 +371,7 @@ android { dependencies { //Handpoint Production SDK (Production devices) - implementation 'com.handpoint.api:sdk:6.x.x' - - //Handpoint Staging/Development SDK (Debug devices) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x' } ``` @@ -354,23 +388,6 @@ allprojects { //Handpoint Production SDK } ``` -```groovy -allprojects { //Handpoint Staging/Development SDK - repositories { - google() - mavenCentral() - maven { - name = "Handpoint Nexus" - url = uri("urlProvided") - credentials { - username = 'usernameProvided' - password = 'passwordProvided' - } - } - } -} -``` - :::tip During the build process, a DEX error may appear. @@ -483,7 +500,8 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md index b6138e7..c7f9e79 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md @@ -30,10 +30,27 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2. SDK distribution** @@ -52,7 +69,7 @@ The latest version is compiled with java **1.8** For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -69,7 +86,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -198,7 +215,7 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds // Use the currency of the country in which you will be deploying terminals } @@ -245,6 +262,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren options.setBudgetNumber("YOUR_BUDGET_NUMBER"); return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override @@ -302,10 +321,27 @@ Please, start an operation (sale,refund etc.) ONLY if you have received the **In **1. Modify the AndroidManifest.xml** -We **strongly** recommend you add the following to your main **``**: +We **strongly** recommend you add the following to your `AndroidManifest.xml`: -```groovy -android:launchMode="singleTask" +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + ``` **2.1 In the gradle.build (app module)** @@ -313,7 +349,7 @@ android:launchMode="singleTask" ```groovy android { defaultConfig { - minSdkVersion 22 //Required to support all PAX & Telpo models + minSdkVersion 22 //Required to support all devices targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true @@ -334,10 +370,7 @@ android { dependencies { //Handpoint Production SDK (Production devices) - implementation 'com.handpoint.api:sdk:6.x.x' - - //Handpoint Staging/Development SDK (Debug devices) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x' } ``` @@ -345,7 +378,7 @@ dependencies { **2.2 In the gradle.build (Top-level build file)** ```groovy -allprojects { //Handpoint Production SDK +allprojects { repositories { google() mavenCentral() @@ -354,23 +387,6 @@ allprojects { //Handpoint Production SDK } ``` -```groovy -allprojects { //Handpoint Staging/Development SDK - repositories { - google() - mavenCentral() - maven { - name = "Handpoint Nexus" - url = uri("urlProvided") - credentials { - username = 'usernameProvided' - password = 'passwordProvided' - } - } - } -} -``` - :::tip During the build process, a DEX error may appear. @@ -483,7 +499,8 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection public OperationStartResult pay() { return this.api.sale(new BigInteger("1000"), Currency.GBP); - // Let´s start our first payment of 10 pounds + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals } @Override From bcd00d416b4dee459ca84336a7fbeeb714e6ae12 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 14 Mar 2023 10:49:03 +0100 Subject: [PATCH 043/115] Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. --- android/androidintegrationguide.md | 4 +- android/androidintroduction.md | 35 ++++++++++++++++-- .../androidintegrationguide.md | 4 +- .../androidintroduction.md | 31 ++++++++++++++-- .../androidintegrationguide.md | 4 +- .../androidintroduction.md | 33 +++++++++++++++-- .../androidintegrationguide.md | 4 +- .../androidintroduction.md | 34 +++++++++++++++-- restapi/restdownloads.md | 2 +- restapi/restobjects.md | 2 +- .../version-REST API 2.10.0/restdownloads.md | 2 +- .../version-REST API 2.10.0/restobjects.md | 2 +- .../version-REST API 2.12.0/restdownloads.md | 2 +- .../version-REST API 2.12.0/restobjects.md | 2 +- .../version-REST API 2.6.0/restobjects.md | 2 +- .../version-REST API 2.7.1/restdownloads.md | 2 +- .../version-REST API 2.7.1/restobjects.md | 2 +- ...intAPIREST2023.postman_collection.json.zip | Bin 0 -> 8687 bytes 18 files changed, 135 insertions(+), 32 deletions(-) create mode 100644 static/files/HandpointAPIREST2023.postman_collection.json.zip diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index 4f6ac87..647643a 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -119,7 +119,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -143,7 +143,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.1001.0,) aar ``` diff --git a/android/androidintroduction.md b/android/androidintroduction.md index 92c9ef2..59142f2 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -54,12 +54,39 @@ The Handpoint Android SDK is available on Maven central as well as the Handpoint The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + ### Gradle Settings For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -76,7 +103,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -109,7 +136,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -133,7 +160,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.1001.0,) aar ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md index 696982d..afb83e8 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintegrationguide.md @@ -119,7 +119,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -143,7 +143,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.0.0,) aar ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md index ba12534..42e1e4d 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md @@ -60,12 +60,37 @@ The Handpoint Android SDK is available on Maven central as well as the Handpoint The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + ### Gradle Settings For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -82,7 +107,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -115,7 +140,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md index 7cf6090..3a13532 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintegrationguide.md @@ -119,7 +119,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -143,7 +143,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.0.1,) aar ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md index 92c9ef2..428605e 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md @@ -54,12 +54,37 @@ The Handpoint Android SDK is available on Maven central as well as the Handpoint The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + ### Gradle Settings For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -76,7 +101,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -109,7 +134,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -133,7 +158,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.0.1,) aar ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md index c7f9e79..c4ca68e 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintegrationguide.md @@ -119,7 +119,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -143,7 +143,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.0.2,) aar ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md index 92c9ef2..d2f574e 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md @@ -43,6 +43,7 @@ Created for humans, coders, geeks, no need of a dark and complex knowledge of th We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + ### SDK distribution The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. @@ -54,12 +55,37 @@ The Handpoint Android SDK is available on Maven central as well as the Handpoint The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + ### Gradle Settings For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:6.x.x' + implementation 'com.handpoint.api:sdk:7.x.x' ``` In the `gradle.build` (Top-level build file) for production terminals (Maven): @@ -76,7 +102,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): For debug terminals (Nexus): ```groovy //Handpoint Staging/Development SDK (Debug terminals) - implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` In the `gradle.build` (Top-level build file) for debug terminals (Nexus): @@ -109,7 +135,7 @@ android { //to add android:exported="true" or android:exported="false" in your activities multiDexEnabled true ndk { - abiFilters "armeabi", "armeabi-v7a", "x86", "mips" + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } @@ -133,7 +159,7 @@ For production terminals: com.handpoint.api sdk - [6.0.0,7.0.0) + [7.0.2,) aar ``` diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index b904728..b3841b2 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. -[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 0694760..dba056b 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -34,7 +34,7 @@ Possible Values: | `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | | `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | | `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md index b904728..b3841b2 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. -[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index 7e2e3a3..9a582a9 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -34,7 +34,7 @@ Possible Values: | `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)**| | `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | | `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md index b904728..b3841b2 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. -[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md index d8fef68..936a39c 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -34,7 +34,7 @@ Possible Values: | `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | | `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | | `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md index 68c4e06..733113e 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md @@ -33,7 +33,7 @@ Possible Values: | `saleReversal`
*String* | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id | | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) | | `tokenizeCard`
*String* | Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) | -| `printReceipt`
*String* | This method sends the merchant or customer receipt to the terminal for printing. The format of the HTML data, passed to the method or stored in the url, must follow this format: [Html Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format) | +| `printReceipt`
*String* | This method sends the merchant or customer receipt to the terminal for printing. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | | `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | | `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restdownloads.md b/restapi_versioned_docs/version-REST API 2.7.1/restdownloads.md index bbfc444..a36213e 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. -[Download this Postman Collection](/files/Handpoint_API_REST_Collection.json.zip) +[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md index 3da1213..c4edfba 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md @@ -34,7 +34,7 @@ Possible Values: | `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)**| | `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | | `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | diff --git a/static/files/HandpointAPIREST2023.postman_collection.json.zip b/static/files/HandpointAPIREST2023.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..7cc9d215d63c23322df00989ff2f462bd714de1f GIT binary patch literal 8687 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 UD Date: Tue, 14 Mar 2023 12:54:55 +0100 Subject: [PATCH 044/115] fix: js SDK v6.3.0 url and release notes (#59) --- javascript/javascriptintroduction.md | 4 ++-- javascript/javascriptreleasenotes.md | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index 2c3a6bb..afb4496 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index f1e51ab..b94f003 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -8,7 +8,10 @@ id: javascriptreleasenotes :::tip Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 6.3.0 +**Features**: +- Metadata ## 6.2.1 From 8c778f0e3272020a37f4f106a6f34cd455ad6f24 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 14 Mar 2023 13:24:25 +0100 Subject: [PATCH 045/115] Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK --- android/androidreleasenotes.md | 16 ++++++++ javascript/javascriptreleasenotes.md | 10 +++++ restapi/restreleasenotes.md | 13 +++++++ windows/windowsevents.md | 2 +- windows/windowsintegrationguide.md | 34 ++++++++--------- windows/windowsreleasenotes.md | 11 ++++++ .../windowsintegrationguide.md | 38 +++++++++---------- .../windowsevents.md | 2 +- .../windowsintegrationguide.md | 32 ++++++++-------- .../windowsevents.md | 2 +- .../windowsintegrationguide.md | 38 +++++++++---------- .../windowsevents.md | 2 +- .../windowsintegrationguide.md | 26 ++++++------- 13 files changed, 138 insertions(+), 88 deletions(-) diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 81cc38d..9362078 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -12,6 +12,22 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: +## 7.1001.0 +**Features**: + + We are introducing a new feature called [**Transaction Metadata**](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + ## 7.0.2 **Features**: diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index b94f003..ff365ca 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -13,6 +13,16 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. **Features**: - Metadata +## 6.3.0 + +**Features**: + +We are introducing a new feature called [**Transaction Metadata**](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + ## 6.2.1 **Fixes**: diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 58acd2e..8e24f93 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,19 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). ## 2.12.0 **Features:** diff --git a/windows/windowsevents.md b/windows/windowsevents.md index 5d410ec..e2e35fe 100644 --- a/windows/windowsevents.md +++ b/windows/windowsevents.md @@ -219,7 +219,7 @@ public void PendingTransactionResult(Device device){ `TransactionResultReady` Method -In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. #### Parameters diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index f58da30..dabc7c4 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -105,7 +105,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -140,7 +140,7 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -227,7 +227,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -258,7 +258,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -410,7 +410,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -544,7 +544,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("***ConnectionStatus*** " + status); if (status == ConnectionStatus.Connected) @@ -563,7 +563,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -795,7 +795,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -834,7 +834,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -915,7 +915,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -946,7 +946,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -1100,7 +1100,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1231,7 +1231,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1829,7 +1829,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 77c54d5..deaa568 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -9,6 +9,17 @@ id: windowsreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 3.4.0 + +**Features** + +We are introducing a new feature called [**Transaction Metadata**](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + ## 3.3.0 **Features:** diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md index 2c327e4..b4c2f73 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -105,7 +105,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -144,7 +144,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -225,7 +225,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -256,7 +256,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -410,7 +410,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -541,7 +541,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -560,7 +560,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -765,7 +765,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -776,7 +776,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -811,7 +811,7 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -898,7 +898,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -929,7 +929,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -1081,7 +1081,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1215,7 +1215,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("***ConnectionStatus*** " + status); if (status == ConnectionStatus.Connected) @@ -1234,7 +1234,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1476,7 +1476,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1562,7 +1562,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1813,7 +1813,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsevents.md index 5d410ec..e2e35fe 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsevents.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsevents.md @@ -219,7 +219,7 @@ public void PendingTransactionResult(Device device){ `TransactionResultReady` Method -In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. #### Parameters diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md index f58da30..a4617db 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -105,7 +105,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -140,7 +140,7 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -227,7 +227,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -258,7 +258,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -410,7 +410,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -544,7 +544,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("***ConnectionStatus*** " + status); if (status == ConnectionStatus.Connected) @@ -563,7 +563,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -795,7 +795,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -915,7 +915,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -946,7 +946,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -1100,7 +1100,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1231,7 +1231,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1578,7 +1578,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md index 5d410ec..e2e35fe 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsevents.md @@ -219,7 +219,7 @@ public void PendingTransactionResult(Device device){ `TransactionResultReady` Method -In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. #### Parameters diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md index f58da30..545fde0 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -105,7 +105,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -140,7 +140,7 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -227,7 +227,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -258,7 +258,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -410,7 +410,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -544,7 +544,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("***ConnectionStatus*** " + status); if (status == ConnectionStatus.Connected) @@ -563,7 +563,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -795,7 +795,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -834,7 +834,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -915,7 +915,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -946,7 +946,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -1100,7 +1100,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1231,7 +1231,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1492,7 +1492,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1578,7 +1578,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1829,7 +1829,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md index 5d410ec..e2e35fe 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsevents.md @@ -219,7 +219,7 @@ public void PendingTransactionResult(Device device){ `TransactionResultReady` Method -In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDJ. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. #### Parameters diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md index f58da30..3b3c855 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -105,7 +105,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -140,7 +140,7 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -227,7 +227,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -258,7 +258,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -410,7 +410,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -563,7 +563,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -795,7 +795,7 @@ namespace GettingStartedApp // Useful information can be accessed through this object like the transaction ID, the amount, etc. } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { // The ConnectionStatus object holds details about the status regarding the connection to the target device. } @@ -946,7 +946,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); } @@ -1100,7 +1100,7 @@ namespace GettingStartedApp Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. ```csharp -public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) +public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1231,7 +1231,7 @@ namespace GettingStartedApp api.Disconnect(); } - public void **[*ConnectionStatusChanged*](#7)**(ConnectionStatus status, Device device) + public void ConnectionStatusChanged(ConnectionStatus status, Device device) { Console.WriteLine("*** ConnectionStatus *** " + status); if (status == ConnectionStatus.Connected) @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void deviceDiscoveryFinished(List devices) { foreach (Device device in devices) { From 0dabbcee3d0aee91997e462325931fcbc96c78eb Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 14 Mar 2023 13:47:24 +0100 Subject: [PATCH 046/115] Fix: JS SDK ReleaseNotes (#61) --- javascript/javascriptreleasenotes.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index ff365ca..f8a2876 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -8,10 +8,6 @@ id: javascriptreleasenotes :::tip Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: -## 6.3.0 - -**Features**: -- Metadata ## 6.3.0 From 28baa177c36b04f37d06db2592dea46fe5402c91 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 14 Mar 2023 17:09:57 +0100 Subject: [PATCH 047/115] Add: new SDKs versions (#62) --- android/androidintroduction.md | 6 +- .../androidintroduction.md | 6 +- .../androidintroduction.md | 6 +- .../androidintroduction.md | 6 +- .../androidintroduction.md | 6 +- .../androidintroduction.md | 8 +- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 368 ++++ .../androideventlisteners.md | 700 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 559 +++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1131 ++++++++++ .../androidreleasenotes.md | 241 ++ .../androidtransactions.md | 585 +++++ ...version-Android SDK 7.1001.0-sidebars.json | 8 + android_versions.json | 1 + .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 687 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 92 + .../javascriptreleasenotes.md | 53 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 220 ++ .../javascripttransactiontypes.md | 454 ++++ ...version-JavaScript SDK 6.3.0-sidebars.json | 8 + javascript_versions.json | 1 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.13.0/restdownloads.md | 10 + .../version-REST API 2.13.0/restendpoints.md | 329 +++ .../restintroduction.md | 50 + .../version-REST API 2.13.0/restobjects.md | 690 ++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 59 + .../version-REST API 2.13.0/restsandbox.md | 44 + .../version-REST API 2.13.0-sidebars.json | 8 + restapi_versions.json | 1 + src/css/custom.css | 2 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 360 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 1951 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 557 +++++ .../windowsreleasenotes.md | 76 + .../windowstransactions.md | 563 +++++ .../version-Windows SDK 3.4.0-sidebars.json | 8 + windows_versions.json | 1 + 50 files changed, 10883 insertions(+), 20 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1001.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1001.0-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 6.3.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.13.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.13.0-sidebars.json create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 3.4.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 3.4.0-sidebars.json diff --git a/android/androidintroduction.md b/android/androidintroduction.md index 59142f2..d9cf12b 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -83,7 +83,7 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:7.x.x' @@ -100,12 +100,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md index 027d8af..8182605 100644 --- a/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md @@ -56,7 +56,7 @@ The latest version is compiled with java **1.8** ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:6.x.x' @@ -73,12 +73,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md index 3227ab0..25898c4 100644 --- a/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md @@ -56,7 +56,7 @@ The latest version is compiled with java **1.8** ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:6.x.x' @@ -73,12 +73,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:6.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md index 42e1e4d..2e65dd6 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md @@ -87,7 +87,7 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:7.x.x' @@ -104,12 +104,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md index 428605e..ffeb184 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md @@ -81,7 +81,7 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:7.x.x' @@ -98,12 +98,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md index d2f574e..b1c4b49 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md @@ -82,7 +82,7 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -For production terminals (Maven): +#### For production terminals (Maven): ```groovy //Handpoint Production SDK (Production terminals) implementation 'com.handpoint.api:sdk:7.x.x' @@ -99,12 +99,12 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): } ``` -For debug terminals (Nexus): +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy - //Handpoint Staging/Development SDK (Debug terminals) + //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' ``` - In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy allprojects { //Handpoint Staging/Development SDK (Debug terminals) diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md new file mode 100644 index 0000000..5f0850d --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md @@ -0,0 +1,368 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1001.0/androideventlisteners.md new file mode 100644 index 0000000..93ffb87 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androideventlisteners.md @@ -0,0 +1,700 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { + // Notify the app user transaction has been started ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1001.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidintegrationguide.md new file mode 100644 index 0000000..647643a --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidintegrationguide.md @@ -0,0 +1,559 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue + // For this sample app we are not going to implement this event + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidmigrationguide.md new file mode 100644 index 0000000..6d0b68f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md new file mode 100644 index 0000000..5bfa2ff --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md @@ -0,0 +1,1131 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md new file mode 100644 index 0000000..9362078 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md @@ -0,0 +1,241 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [**Transaction Metadata**](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidtransactions.md new file mode 100644 index 0000000..fdfbc38 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidtransactions.md @@ -0,0 +1,585 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.1001.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1001.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1001.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index c23190f..b15cc1e 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1001.0", "Android SDK 7.0.2", "Android SDK 7.0.1", "Android SDK 7.0.0", diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptintroduction.md new file mode 100644 index 0000000..afb4496 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md new file mode 100644 index 0000000..067a170 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md @@ -0,0 +1,687 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptquickintegration.md new file mode 100644 index 0000000..f3e18ce --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptquickintegration.md @@ -0,0 +1,92 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example 0821032395-PAXA920. If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable environmentIsDevelopment to true otherwise change it to false. + +4)Open the html file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md new file mode 100644 index 0000000..f8a2876 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md @@ -0,0 +1,53 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [**Transaction Metadata**](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..b6241c0 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptterminalmanagement.md @@ -0,0 +1,220 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascripttransactiontypes.md new file mode 100644 index 0000000..8b66b3e --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascripttransactiontypes.md @@ -0,0 +1,454 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } +} + +Handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleAndTokenization('1000', 'USD', saleOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale and Tokenization Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +Handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +Handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction Status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Refund Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +Handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Sale Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 6.3.0-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 6.3.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 6.3.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 9563bfa..aaaac31 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 6.3.0", "JavaScript SDK 6.2.1", "Javascript SDK 6.2.0", "JavaScript SDK 6.1.0", diff --git a/restapi_versioned_docs/version-REST API 2.13.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.13.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.13.0/restdownloads.md new file mode 100644 index 0000000..b3841b2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. + +[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.13.0/restendpoints.md new file mode 100644 index 0000000..6c9b4ca --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restendpoints.md @@ -0,0 +1,329 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.13.0/restintroduction.md new file mode 100644 index 0000000..4ca8dfd --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md new file mode 100644 index 0000000..dba056b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md @@ -0,0 +1,690 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} + +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.13.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md new file mode 100644 index 0000000..8e24f93 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md @@ -0,0 +1,59 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.13.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.13.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.13.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.13.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.13.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 25ee2b5..0b040c0 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.13.0", "REST API 2.12.0", "REST API 2.10.0", "REST API 2.7.1", diff --git a/src/css/custom.css b/src/css/custom.css index 41cfeb5..579f716 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -117,7 +117,7 @@ color: white; /* Navbar Items Font Size */ .navbar__item { - font-size: 9.5px; + font-size: 9px; } /* ////////////////////////// */ diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md new file mode 100644 index 0000000..09b7ce9 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md @@ -0,0 +1,360 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.UseDevice(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.UseDevice(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set parameter + +`SetParameter` Method + +Allows developers to optionally change several internal parameters of the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| +| `value` Required
*String* | New value of the parameter.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Changes the bluetooth name of card reader +api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md new file mode 100644 index 0000000..dabc7c4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md @@ -0,0 +1,1951 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void deviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + // Put the name of your device, it is the composition of: serial number - device model. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("9822032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void deviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void deviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md new file mode 100644 index 0000000..60b7127 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -0,0 +1,557 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md new file mode 100644 index 0000000..deaa568 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md @@ -0,0 +1,76 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 3.4.0 + +**Features** + +We are introducing a new feature called [**Transaction Metadata**](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowstransactions.md new file mode 100644 index 0000000..4b42a92 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowstransactions.md @@ -0,0 +1,563 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Requiredv*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the gateway| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| diff --git a/windows_versioned_sidebars/version-Windows SDK 3.4.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 3.4.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 3.4.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 7ccd894..543a0de 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 3.4.0", "Windows SDK 3.3.0", "Windows SDK 3.2.5", "Windows SDK 3.2.4", From cc446a4fa0055b4b995076c8bdfa4d6a8b0846b6 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 3 May 2023 19:34:07 +0200 Subject: [PATCH 048/115] Add: Pax IM30 (#64) --- src/pages/cpdocs.js | 182 ++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 82 deletions(-) diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index e540bbd..b71ff2c 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -18,14 +18,14 @@ import { Button, Element, Events, animateScroll as scroll, scrollSpy, scroller } function CpDocs() { return ( - + - +
-
+
-
-
+
+

Integration Paths



@@ -67,15 +67,15 @@ function CpDocs() {



-
- -
+
+ +
-
+
- +
); } @@ -210,73 +210,73 @@ function IntegrationPaths() {
-
-
-

- Cloud Integration -

-

The Handpoint cloud payments solution allows your point of sale to easily communicate with - payment terminals via the internet (cellular or wifi). Only an API key is required to start sending sales to the card reader and get back the transaction result to your software when the operation is completed. - No other configuration is required, the merchant only needs to connect the terminal to Wifi and open the payment application to be able to start taking payments. Card data is never sent unmasked to your software so you can be kept out of PCI scope.

-
- cloud integration +
+
+

+ Cloud Integration +

+

The Handpoint cloud payments solution allows your point of sale to easily communicate with + payment terminals via the internet (cellular or wifi). Only an API key is required to start sending sales to the card reader and get back the transaction result to your software when the operation is completed. + No other configuration is required, the merchant only needs to connect the terminal to Wifi and open the payment application to be able to start taking payments. Card data is never sent unmasked to your software so you can be kept out of PCI scope.

+
+ cloud integration +
-


-
-
-

- Native Integration -

-

The Handpoint native integration allows you to run your own Android application on the payment terminal. Your application embeds the Handpoint - Android SDK in order to process payments. This all-in-one solution puts you in control of the checkout experience and does not require any separate application for payment processing. - Card data is never sent unmasked to your application so you can be kept out of PCI scope.

-
- native integration +
+
+

+ Native Integration +

+

The Handpoint native integration allows you to run your own Android application on the payment terminal. Your application embeds the Handpoint + Android SDK in order to process payments. This all-in-one solution puts you in control of the checkout experience and does not require any separate application for payment processing. + Card data is never sent unmasked to your application so you can be kept out of PCI scope.

+
+ native integration +
-


-
-
-

- Bluetooth Integration -

-

The Handpoint bluetooth integration allows your point of sale to easily communicate with the Handpoint HiLite terminal. - The HiLite is Handpoint's ultra portable card reader for small and/or highly mobile merchants. With the HiLite, merchants can start accepting - payments on the go!

-
- HiLite integration +
+
+

+ Bluetooth Integration +

+

The Handpoint bluetooth integration allows your point of sale to easily communicate with the Handpoint HiLite terminal. + The HiLite is Handpoint's ultra portable card reader for small and/or highly mobile merchants. With the HiLite, merchants can start accepting + payments on the go!

+
+ HiLite integration +
-


-
-
-

- Lightning Integration -

-

The Handpoint HiPro is an all-in-one payment terminal compatible with iOS devices. The lightning port is used for the communication - between the iOS phone or ipod and the payment terminal. This is the perfect line buster for busy retail environments. With its integrated scanner It can also be used to - scan barcodes and manage inventory as well as taking payments on the spot, directly in the store aisles.

-
- HiPro integration +
+
+

+ Lightning Integration +

+

The Handpoint HiPro is an all-in-one payment terminal compatible with iOS devices. The lightning port is used for the communication + between the iOS phone or ipod and the payment terminal. This is the perfect line buster for busy retail environments. With its integrated scanner It can also be used to + scan barcodes and manage inventory as well as taking payments on the spot, directly in the store aisles.

+
+ HiPro integration +
-
@@ -290,42 +290,42 @@ function Standalone() {
-
-
-

- Standalone smartPOS application -

-

Handpoint offers a basic standalone application allowing your merchants to take payments without being connected to a point of sale software. - When the card reader is used in standalone mode, the merchant can simply type in an amount and start processing payments. - The Handpoint standalone application offers a full set of functionalities, from powerful analytics, to end-of-day reports and manual card entry for over the phone transactions.

-
- standalone terminal -
-

Standalone terminals are not integrated to your software. However, they can be turned from standalone to cloud integrated by the flip - of a switch. You can therefore start shipping standalone terminals to your merchants and when your integration is ready, upgrade the terminals to start accepting cloud payments. - Standalone mode can also be used as a fallback method for the merchant to continue processing payments even if the point of sale is down.

-
- integrated mode +
+
+

+ Standalone smartPOS application +

+

Handpoint offers a basic standalone application allowing your merchants to take payments without being connected to a point of sale software. + When the card reader is used in standalone mode, the merchant can simply type in an amount and start processing payments. + The Handpoint standalone application offers a full set of functionalities, from powerful analytics, to end-of-day reports and manual card entry for over the phone transactions.

+
+ standalone terminal +
+

Standalone terminals are not integrated to your software. However, they can be turned from standalone to cloud integrated by the flip + of a switch. You can therefore start shipping standalone terminals to your merchants and when your integration is ready, upgrade the terminals to start accepting cloud payments. + Standalone mode can also be used as a fallback method for the merchant to continue processing payments even if the point of sale is down.

+
+ integrated mode +
-


-
-
-

- standalone mPOS application -

-

The Handpoint mPOS application is available on the Google Play Store and Apple App Store. - The mPOS application is connected via bluetooth with the HiLite payment terminal and offers the same powerful yet simple functionalities as the standalone smartPOS application. It is a perfect solution for occasional merchants needing to accept payments on the move.

-
- mPOS payments application +
+
+

+ standalone mPOS application +

+

The Handpoint mPOS application is available on the Google Play Store and Apple App Store. + The mPOS application is connected via bluetooth with the HiLite payment terminal and offers the same powerful yet simple functionalities as the standalone smartPOS application. It is a perfect solution for occasional merchants needing to accept payments on the move.

+
+ mPOS payments application +
-
@@ -563,7 +563,7 @@ function TableTerminals() {
@@ -571,7 +571,25 @@ function TableTerminals() {
+

+
+
+

+ PAX IM30 +

+
+ + +
+
+ +
+ + +
// From 4328c7e510fceb24747c1130d5f945ad598041aa Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 25 May 2023 15:09:51 +0200 Subject: [PATCH 049/115] Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments --- android/androiddevicemanagement.md | 35 +++++++++ android/androidobjects.md | 2 +- android/androidreleasenotes.md | 4 + android/androidtransactions.md | 1 + docusaurus.config.js | 8 +- javascript/javascriptobjects.md | 17 +++- javascript/javascriptreleasenotes.md | 5 ++ javascript/javascriptterminalmanagement.md | 35 +++++++++ javascript/javascripttransactiontypes.md | 25 ++++-- restapi/restendpoints.md | 90 +++++++++++++++++++++- restapi/restobjects.md | 7 +- restapi/restreleasenotes.md | 10 +++ windows/windowsdevicemanagement.md | 36 ++++++++- windows/windowsobjects.md | 12 +++ windows/windowsreleasenotes.md | 4 + windows/windowstransactions.md | 1 + 16 files changed, 273 insertions(+), 19 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index 5f0850d..53b4c1f 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -366,3 +366,38 @@ The merchant should be notified about the update process. | Parameter | Notes | | ----------- | ----------- | | `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status + +`getTransactionStatus` Method + +The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. + +The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The reference of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android/androidobjects.md b/android/androidobjects.md index 5bfa2ff..fbf0afe 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -664,7 +664,7 @@ Object containing information about the financial operation being performed. | Parameter | Description | | ----------- | ----------- | | `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1.0** of the Android SDK.| +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1001.0** of the Android SDK.| | `errorMessage`
*String* | Detailed reason for the transaction error. | diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index ca70226..4643aa7 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -12,6 +12,10 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: +## 7.1002.0 +**Features**: + +We are excited to announce the launch of a new feature: [**Get Transaction Status**](androiddevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](androidobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions ## 7.1001.0 **Features**: diff --git a/android/androidtransactions.md b/android/androidtransactions.md index fdfbc38..06a1447 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -583,3 +583,4 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + diff --git a/docusaurus.config.js b/docusaurus.config.js index 72869b8..86ff891 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,7 +229,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -242,7 +242,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'restapi', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'restapi', routeBasePath: 'restapi', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -255,7 +255,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -279,7 +279,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'android', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: './android', routeBasePath: 'android', sidebarPath: require.resolve('./sidebarsAndroid.js'), diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 067a170..079eca8 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -684,4 +684,19 @@ An object to store metadata. "metadata5": "data5" } } -``` \ No newline at end of file +``` + + + +## Operation Started Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.0.0** of the JavaScript SDK.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 025ea2c..f17a397 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -9,6 +9,11 @@ id: javascriptreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.0.0 +**Features**: + +We are excited to announce the launch of a new feature: [**Get Transaction Status**](javascriptterminalmanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](javascriptobjects.md#transaction-reference) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions + ## 6.3.0 **Features**: diff --git a/javascript/javascriptterminalmanagement.md b/javascript/javascriptterminalmanagement.md index b6241c0..d93ba92 100644 --- a/javascript/javascriptterminalmanagement.md +++ b/javascript/javascriptterminalmanagement.md @@ -218,3 +218,38 @@ Handpoint.update(CallbackFunction(stat){...}); | ----------- | ----------- | | **Update Response**|A financial response object.| + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. + +The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*string* | The `transactionReference` of the transaction to query.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| The status of the requested transaction.| \ No newline at end of file diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 8b66b3e..cc6b371 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -58,16 +58,19 @@ var saleOptions = { } } -Handpoint.sale('1000', 'USD', saleOptions, function (stat) { +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { console.log('Transaction status received -> '+ stat.message) }); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -117,14 +120,19 @@ var saleOptions = { ], } -Handpoint.saleAndTokenization('1000', 'USD', saleOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Sale and Tokenization Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Transaction Recovery{#6} @@ -309,16 +317,19 @@ var saleOptions = { customerReference: "MyCustomReference", } -Handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { - console.log('Transaction Status received -> '+ stat.message) +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) }); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Sale Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 6c9b4ca..dcf2ecb 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -106,7 +106,8 @@ Transaction Request without callbackUrl and token "currency":"EUR", "terminal_type":"PAXA920", "serial_number":"1547854757", - "customerReference":"op15248" + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" }' \\ Transaction Request with callbackUrl and token -d '{ @@ -117,7 +118,8 @@ Transaction Request with callbackUrl and token "serial_number":"1547854757", "customerReference":"op15248", "callbackUrl":"https://url.where.the.result.is.served.com", - "token":"123456789" + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" }' \\ "https://cloud.handpoint.com/transactions" (production) "https://cloud.handpoint.io/transactions" (development) @@ -127,12 +129,14 @@ RESPONSES: Transaction Request without callbackUrl { "transactionResultId": "0821032398-1628774190395", - "statusMessage": "Operation Accepted" + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" } Transaction Request with callbackUrl and token { - "statusMessage": "Operation Accepted" + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" } Code 400 Ex:DeviceIsBusy @@ -327,3 +331,81 @@ Error example response (using invalid guid): +## /transactions/{transactionReference}/status + +The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. To use this endpoint, you would make an HTTP GET request to the specified endpoint URL, replacing {transactionReference} with the actual transaction reference you want to query. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction status. | + +**Returns** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object). The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. | +| **Not Found** | Response code **404**. The `transactionReference` was not found in the database. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://cloud.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + diff --git a/restapi/restobjects.md b/restapi/restobjects.md index dba056b..dee73aa 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -132,6 +132,7 @@ An object holding information about the result of a transaction. | `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| | `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| | `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The `transactionReference` of the transaction to query| **Code example** @@ -199,7 +200,8 @@ An object holding information about the result of a transaction. "requestedAmount": 100, "tipPercentage": 0, "recoveredTransaction": false, - "cardHolderName": "Mr/Mrs card holder full name" + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" } ```` @@ -231,6 +233,7 @@ An object to store information about the request sent to the payment terminal. | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))).| **Code example** @@ -245,6 +248,7 @@ An object to store information about the request sent to the payment terminal. "customerReference": "storeSale12548", "callbackUrl": "https://result.com", "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", "tipConfiguration": { "baseAmount": "2000", "tipPercentages": [5,10,15,20,25], @@ -281,6 +285,7 @@ An object to store information about the request sent to the payment terminal. "terminal_type": "PAXA920", "serial_number": "1547854757", "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", "tipConfiguration": { "baseAmount": "2000", "tipPercentages": [5,10,15,20,25], diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 8e24f93..7f20834 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,16 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 2.14.0 +**Features:** + +We are excited to announce the launch of a new feature: [**Get Transaction Status**](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus), allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. + +***Please note**: When a transaction is started from the REST API, a `transactionReference` field is needed in the body of the [request](restobjects.md#transactionRequest). This field is a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) for the transaction resource that you want to create or update. It helps to ensure consistency and avoid conflicts between concurrent requests. + +This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions. + + ## 2.13.0 **Features:** diff --git a/windows/windowsdevicemanagement.md b/windows/windowsdevicemanagement.md index 09b7ce9..41205db 100644 --- a/windows/windowsdevicemanagement.md +++ b/windows/windowsdevicemanagement.md @@ -357,4 +357,38 @@ Invoked when the status of the connection with the payment terminal changes. | Parameter | Notes | | ----------- | ----------- | -| **None**| No information is returned.| \ No newline at end of file +| **None**| No information is returned.| + +## Get Transaction Status + +`GetTransactionStatus` Method + +The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. + +The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*transactionResultReady*](windowsevents.md#11)** + +Invoked when the result of the getTransactionStatus request is available. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| Returns `true` or `false` if status has been requested| \ No newline at end of file diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index 60b7127..042543d 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -555,3 +555,15 @@ Object used to echo metadata1-5, in the transaction result, if it was set as an } } ``` + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| \ No newline at end of file diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index deaa568..2bd4f3e 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -9,6 +9,10 @@ id: windowsreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 4.0.0 +**Features** + +We are excited to announce the launch of a new feature: [**Get Transaction Status**](windowsdevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](windowsobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions. ## 3.4.0 diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 4b42a92..3246f02 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -561,3 +561,4 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | | `Boolean`| `true` if the operation was successfully sent to the payment terminal| + From 7ba0aa823ec0e0b846d98080104fd10ea8ff2103 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 31 May 2023 19:48:48 +0200 Subject: [PATCH 050/115] add: diagrams, finStatus, Postman collection (#67) --- android/androidobjects.md | 4 +- docusaurus.config.js | 8 ++-- javascript/javascriptobjects.md | 5 ++- javascript/javascriptreleasenotes.md | 8 +++- javascript/javascripttransactiontypes.md | 37 +++++++++++------- restapi/restdownloads.md | 2 +- restapi/restendpoints.md | 8 ++-- restapi/restobjects.md | 5 ++- restapi/restreleasenotes.md | 5 +-- ...intRESTAPI2023.postman_collection.json.zip | Bin 0 -> 8763 bytes static/img/RestAPIexample.png | Bin 0 -> 182932 bytes .../getTransactionStatusEndpoint.drawio.png | Bin 0 -> 97953 bytes windows/windowsobjects.md | 4 +- 13 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 static/files/HandpointRESTAPI2023.postman_collection.json.zip create mode 100644 static/img/RestAPIexample.png create mode 100644 static/img/getTransactionStatusEndpoint.drawio.png diff --git a/android/androidobjects.md b/android/androidobjects.md index fbf0afe..6358f82 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -377,7 +377,7 @@ An enum representing different statuses of a finalized transaction **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` Description of the different financial statuses: @@ -390,6 +390,8 @@ Description of the different financial statuses: | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | +| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | +| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | ## Handpoint Credentials{#43} diff --git a/docusaurus.config.js b/docusaurus.config.js index 86ff891..72869b8 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,7 +229,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -242,7 +242,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'restapi', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: 'restapi', routeBasePath: 'restapi', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -255,7 +255,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -279,7 +279,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'android', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: './android', routeBasePath: 'android', sidebarPath: require.resolve('./sidebarsAndroid.js'), diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 079eca8..138f50a 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -479,7 +479,7 @@ An enum representing different statuses for a completed transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` Description of the different financial statuses: @@ -492,6 +492,9 @@ Description of the different financial statuses: | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | +| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | + diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index f17a397..a218a57 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -10,9 +10,13 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: ## 7.0.0 -**Features**: +**BREAKING CHANGE:** + +We are excited to announce the launch of a new feature: [**Get Transaction Status**](javascriptterminalmanagement.md#17). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](javascriptobjects.md#transaction-reference) obtained when a new transaction has been started. -We are excited to announce the launch of a new feature: [**Get Transaction Status**](javascriptterminalmanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](javascriptobjects.md#transaction-reference) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions +When starting a new transaction (Sale, Refund,... ) the `OperationStartResult` object will contain two attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. +- `transactionResult`: Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. ## 6.3.0 diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index cc6b371..cff61b8 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -70,7 +70,7 @@ let result = await operationStartedResult.transactionResult | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| @@ -132,7 +132,7 @@ let result = await operationStartedResult.transactionResult | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| ## Transaction Recovery{#6} @@ -194,14 +194,17 @@ var saleReversalOptions = { ], } -Handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Sale Reversal Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| ## Refund{#9} @@ -240,17 +243,20 @@ var refundOptions = { ], } -Handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult // Linked Refund -Handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Refund Response**|A[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| ## Refund Reversal{#10} @@ -285,14 +291,17 @@ var refundReversalOptions = { ], } -Handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Refund Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| ## MoTo Sale @@ -329,7 +338,7 @@ let result = await operationStartedResult.transactionResult | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the [transaction result](javascriptobjects.md#18) object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| @@ -356,7 +365,7 @@ var refundOptions = { customerReference: "MyCustomReference" } -Handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); // Linked Refund Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); @@ -366,7 +375,7 @@ Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refu | Parameter | Notes | | ----------- | ----------- | -| **Refund Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| ## MoTo Reversal @@ -390,14 +399,14 @@ var moToReversalOptions = { customerReference: "MyCustomReference" } -Handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); ``` **Returns** | Parameter | Notes | | ----------- | ----------- | -| **Sale Reversal Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index b3841b2..6dc465d 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. -[Download this Postman Collection](/files/HandpointAPIREST2023.postman_collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointRESTAPI2023.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index dcf2ecb..4cf2725 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -335,19 +335,21 @@ Error example response (using invalid guid): The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. To use this endpoint, you would make an HTTP GET request to the specified endpoint URL, replacing {transactionReference} with the actual transaction reference you want to query. +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | | `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction status. | **Returns** | Response | Response Code | | ----------- | ----------- | -| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object). The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. | -| **Not Found** | Response code **404**. The `transactionReference` was not found in the database. | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object). Here we have two possible scenarios:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. Consulting the [finStatus](restobjects.md#financialStatus) field we can know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the database. The Gateway has no record of that `transactionReference` (although it might change in the near future). The [finStatus](restobjects.md#financialStatus) received in this case will be UNKNOWN| +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check the API Key used. | **Code Example** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index dee73aa..67f68c5 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -49,7 +49,7 @@ Possible Values: An enum representing different statuses of a completed transaction. -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` Description of the different financial statuses: @@ -58,10 +58,13 @@ Description of the different financial statuses: | `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | | `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `REFUNDED`
| The transaction has been refunded by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | +| `IN_PROGRESS`
| The`transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change.| diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 7f20834..5338920 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -14,10 +14,9 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. We are excited to announce the launch of a new feature: [**Get Transaction Status**](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus), allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. -***Please note**: When a transaction is started from the REST API, a `transactionReference` field is needed in the body of the [request](restobjects.md#transactionRequest). This field is a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) for the transaction resource that you want to create or update. It helps to ensure consistency and avoid conflicts between concurrent requests. - -This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions. +***Please note**: When a transaction is started from the REST API, a `transactionReference` field is needed in the body of the [request](restobjects.md#transactionRequest) to be able to check the status of the transaction later. The value must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) for the transaction that you want to start. It helps to ensure consistency and avoid conflicts between concurrent requests. +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) ## 2.13.0 diff --git a/static/files/HandpointRESTAPI2023.postman_collection.json.zip b/static/files/HandpointRESTAPI2023.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..f8a70ab09cf7ace87ac8bb4d61fa4b6e5b95f7fd GIT binary patch literal 8763 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 z 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

vR%Rl)z$wTwy+)S+u<~#4_ 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≪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 VE*N<6qL~bQv@cy%FH*I}{tJMbPK^Kn literal 0 HcmV?d00001 diff --git a/static/img/getTransactionStatusEndpoint.drawio.png b/static/img/getTransactionStatusEndpoint.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..b72c7c67187c495d95fc98de078f52b8135d72b6 GIT binary patch literal 97953 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

MB9M(Un|#h>p;3Z?iHQkh_KXJ}JgIV9 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 | Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | +| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | From 406d5743dd669f6d2249ff4fa3eac079aa610cc7 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 9 Jun 2023 13:08:46 +0200 Subject: [PATCH 051/115] Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine --- android/androiddevicemanagement.md | 8 +++---- android/androidobjects.md | 6 ++--- android/androidreleasenotes.md | 4 ++-- android/androidtransactions.md | 22 +++++++++---------- javascript/javascriptobjects.md | 6 ++--- javascript/javascriptreleasenotes.md | 8 +++---- .../javascriptobjects.md | 4 ++-- .../javascriptobjects.md | 4 ++-- .../javascriptobjects.md | 4 ++-- .../javascriptobjects.md | 4 ++-- .../javascriptobjects.md | 4 ++-- restapi/restobjects.md | 4 ++-- restapi/restreleasenotes.md | 6 +++-- .../version-REST API 2.10.0/restobjects.md | 4 ++-- .../version-REST API 2.12.0/restobjects.md | 4 ++-- .../version-REST API 2.13.0/restobjects.md | 4 ++-- .../version-REST API 2.6.0/restobjects.md | 4 ++-- .../version-REST API 2.7.1/restobjects.md | 4 ++-- windows/windowsdevicemanagement.md | 9 ++++---- windows/windowsobjects.md | 4 ++-- windows/windowsreleasenotes.md | 11 ++++++---- .../windowsobjects.md | 4 ++-- .../windowsobjects.md | 4 ++-- .../windowsobjects.md | 4 ++-- .../windowsobjects.md | 4 ++-- .../windowsobjects.md | 4 ++-- 26 files changed, 76 insertions(+), 72 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index 53b4c1f..d503a2c 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -367,19 +367,19 @@ The merchant should be notified about the update process. | ----------- | ----------- | | `Boolean`| `True` if the operation was successfully sent to device.| -## Get Transaction Status +## Get Transaction Status{#getTransactionStatus} `getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*String* | The reference of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + **Code example** diff --git a/android/androidobjects.md b/android/androidobjects.md index 6358f82..a0b006f 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -383,7 +383,7 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | +| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the SDK couldn't get a response from the Gateway and therefore does not know the outcome of the transaction. This status is VERY RARE, when you receive this status you can start querying the [get transaction status](androiddevicemanagement.md#getTransactionStatus) endpoint with the `transactionReference` received at the start of the financial operation to know if the transaction was approved or declined.| | `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| @@ -655,7 +655,7 @@ options.setChannel(MoToChannel.TO); ``` -## Operation Start Result +## Operation Start Result {#OperationStartResult} `OperationStartResult` Object @@ -666,7 +666,7 @@ Object containing information about the financial operation being performed. | Parameter | Description | | ----------- | ----------- | | `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1001.0** of the Android SDK.| +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| | `errorMessage`
*String* | Detailed reason for the transaction error. | diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 4643aa7..96800bc 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -15,12 +15,12 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1002.0 **Features**: -We are excited to announce the launch of a new feature: [**Get Transaction Status**](androiddevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](androidobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. ## 7.1001.0 **Features**: - We are introducing a new feature called [**Transaction Metadata**](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 06a1447..1e7a930 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -69,7 +69,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Sale And Tokenize Card{#3} @@ -131,7 +131,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -179,7 +179,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund{#5} @@ -226,7 +226,7 @@ Invoked when the terminal finishes processing the transaction | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund reversal{#6} @@ -273,7 +273,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Sale{#7} @@ -318,7 +318,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| @@ -365,7 +365,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| ## MoTo Reversal{#9} @@ -408,7 +408,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| ## Signature result @@ -450,7 +450,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -543,7 +543,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Card PAN{#13} @@ -582,5 +582,5 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 138f50a..372acf9 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| @@ -691,7 +691,7 @@ An object to store metadata. -## Operation Started Result +## Operation Start Result `OperationStartResult` Object diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index a218a57..760949f 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -12,11 +12,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 **BREAKING CHANGE:** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](javascriptterminalmanagement.md#17). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](javascriptobjects.md#transaction-reference) obtained when a new transaction has been started. +We are introducing a new feature called [**Get Transaction Status**](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [**transaction reference**](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. -When starting a new transaction (Sale, Refund,... ) the `OperationStartResult` object will contain two attributes: -- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. -- `transactionResult`: Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. +When starting a new financial operation (sale,refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. ## 6.3.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md index 55f2960..d2ef942 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md @@ -119,8 +119,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | A URL containing the customer receipt in HTML format| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the device| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| -| `efttimestamp`
*String * | Time of the transaction| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| +| `efttimestamp`
*BigString* | Time of the transaction| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md index b9d047e..a0d00fe 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md index 3380930..264317b 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md index 067a170..64f8953 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md index 3380930..264317b 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 67f68c5..87c6d89 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -100,8 +100,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 5338920..9880b1b 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -12,9 +12,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.14.0 **Features:** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus), allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. -***Please note**: When a transaction is started from the REST API, a `transactionReference` field is needed in the body of the [request](restobjects.md#transactionRequest) to be able to check the status of the transaction later. The value must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) for the transaction that you want to start. It helps to ensure consistency and avoid conflicts between concurrent requests. +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: ![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index 9a582a9..18a0706 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md index 936a39c..8665bc2 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md index dba056b..c96fff0 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md index 733113e..f5d4857 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md @@ -86,8 +86,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | A URL containing the customer receipt in HTML format | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field | | `deviceStatus`
[*DeviceStatus*](#device-status) | Status of the device | -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid | -| `efttimestamp`
*Date* | Time of the transaction | +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid | +| `efttimestamp`
*BigString* | Time of the transaction | | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed. | | `errorMessage`
*String* | Detailed reason for the transaction error | | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation | diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md index c4edfba..a397551 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md @@ -98,8 +98,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/windows/windowsdevicemanagement.md b/windows/windowsdevicemanagement.md index 41205db..46a6b23 100644 --- a/windows/windowsdevicemanagement.md +++ b/windows/windowsdevicemanagement.md @@ -361,17 +361,16 @@ Invoked when the status of the connection with the payment terminal changes. ## Get Transaction Status -`GetTransactionStatus` Method +`getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. -#### Parameters +**Parameters** | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object.| **Code example** diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index e4296a6..df257f2 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 2bd4f3e..c09f2df 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -10,15 +10,18 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: ## 4.0.0 -**Features** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](windowsdevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](windowsobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions. +**BREAKING CHANGE:** -## 3.4.0 +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 **Features** -We are introducing a new feature called [**Transaction Metadata**](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md index a85d569..d8acf1a 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md @@ -30,8 +30,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | A URL containing the customer receipt in HTML format| | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the device| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| -| `efttimestamp`
*Date* | Time of the transaction| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| +| `efttimestamp`
*BigString* | Time of the transaction| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md index ac71adf..072a7a6 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats| | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md index f4ab24e..e3de453 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md index b2dd3a7..431e1dd 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md index 60b7127..d1e779f 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| From de38a224328efebdab8e274055985d257fe2574f Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 12 Jun 2023 08:24:04 +0000 Subject: [PATCH 052/115] Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel --- android/androiddevicemanagement.md | 6 ++++++ android/androidobjects.md | 12 ++++++------ docusaurus.config.js | 8 ++++---- javascript/javascriptobjects.md | 14 +++++++------- javascript/javascriptreleasenotes.md | 7 ++++--- javascript/javascriptterminalmanagement.md | 11 ++++++++--- restapi/restendpoints.md | 14 ++++++++++---- restapi/restobjects.md | 18 ++++++++---------- windows/windowsdevicemanagement.md | 5 +++++ windows/windowsobjects.md | 12 ++++++------ 10 files changed, 64 insertions(+), 43 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index d503a2c..b9453e5 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -373,6 +373,12 @@ The merchant should be notified about the update process. If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful +- DECLINED - Transaction was declined +- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. + **Parameters** diff --git a/android/androidobjects.md b/android/androidobjects.md index a0b006f..8da6340 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -383,15 +383,15 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the SDK couldn't get a response from the Gateway and therefore does not know the outcome of the transaction. This status is VERY RARE, when you receive this status you can start querying the [get transaction status](androiddevicemanagement.md#getTransactionStatus) endpoint with the `transactionReference` received at the start of the financial operation to know if the transaction was approved or declined.| -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the SDK couldn't get a response from the Gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the SDK has a retry mechanism that will attempt to get the transaction status several times (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method to directly query the Handpoint Gateway and know if the transaction was approved or declined.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | ## Handpoint Credentials{#43} diff --git a/docusaurus.config.js b/docusaurus.config.js index 72869b8..86ff891 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,7 +229,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -242,7 +242,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'restapi', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'restapi', routeBasePath: 'restapi', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -255,7 +255,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -279,7 +279,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'android', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: './android', routeBasePath: 'android', sidebarPath: require.resolve('./sidebarsAndroid.js'), diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 372acf9..a789697 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -485,15 +485,15 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](javascriptterminalmanagement.md#17) method to directly query the Handpoint gateway and know if the transaction was approved or declined.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | @@ -701,5 +701,5 @@ Object containing information about the financial operation being performed. | Parameter | Description | | ----------- | ----------- | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.0.0** of the JavaScript SDK.| +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| | `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 760949f..98c0f37 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -12,9 +12,10 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 **BREAKING CHANGE:** -We are introducing a new feature called [**Get Transaction Status**](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [**transaction reference**](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. -When starting a new financial operation (sale,refund etc.) the `OperationStartResult` object will contain two new attributes: + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: - `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. - `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. @@ -22,7 +23,7 @@ When starting a new financial operation (sale,refund etc.) the `OperationStartRe **Features**: -We are introducing a new feature called [**Transaction Metadata**](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. diff --git a/javascript/javascriptterminalmanagement.md b/javascript/javascriptterminalmanagement.md index d93ba92..2b9c36d 100644 --- a/javascript/javascriptterminalmanagement.md +++ b/javascript/javascriptterminalmanagement.md @@ -224,9 +224,14 @@ Handpoint.update(CallbackFunction(stat){...}); `getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful +- DECLINED - Transaction was declined +- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. **Parameters** @@ -234,7 +239,7 @@ The method accesses a transaction tracking system or database to obtain real-tim | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*string* | The `transactionReference` of the transaction to query.| +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| **Code example** diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 4cf2725..8907897 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -333,7 +333,13 @@ Error example response (using invalid guid): ## /transactions/{transactionReference}/status -The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. To use this endpoint, you would make an HTTP GET request to the specified endpoint URL, replacing {transactionReference} with the actual transaction reference you want to query. +The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful +- DECLINED - Transaction was declined +- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. ![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) @@ -342,14 +348,14 @@ The /transactions/{transactionReference}/status endpoint is a RESTful API endpoi | Parameter | Notes | | ----------- | ----------- | | `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction status. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | **Returns** | Response | Response Code | | ----------- | ----------- | -| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object). Here we have two possible scenarios:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. Consulting the [finStatus](restobjects.md#financialStatus) field we can know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the database. The Gateway has no record of that `transactionReference` (although it might change in the near future). The [finStatus](restobjects.md#financialStatus) received in this case will be UNKNOWN| -| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check the API Key used. | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNKNOWN` (NOT FOUND)| +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | **Code Example** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 87c6d89..6ba5438 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -55,17 +55,15 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint to directly query the Handpoint gateway and know if the transaction was approved or declined.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | -| `REFUNDED`
| The transaction has been refunded by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The`transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change.| - +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | @@ -135,7 +133,7 @@ An object holding information about the result of a transaction. | `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| | `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| | `cardHolderName`
*String * | Name of the cardholder| -| `transactionReference`
*String* | The `transactionReference` of the transaction to query| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| **Code example** @@ -236,7 +234,7 @@ An object to store information about the request sent to the payment terminal. | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `transactionReference`
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))).| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| **Code example** diff --git a/windows/windowsdevicemanagement.md b/windows/windowsdevicemanagement.md index 46a6b23..3205a34 100644 --- a/windows/windowsdevicemanagement.md +++ b/windows/windowsdevicemanagement.md @@ -365,6 +365,11 @@ Invoked when the status of the connection with the payment terminal changes. If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful +- DECLINED - Transaction was declined +- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. **Parameters** diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index df257f2..b53ca12 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -384,15 +384,15 @@ An enum representing different final statuses of a transaction. | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method to directly query the Handpoint gateway and know if the transaction was approved or declined.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | From ac71d5384b0a20d7346c3ade6293273dde068500 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 19 Jun 2023 16:50:20 +0200 Subject: [PATCH 053/115] Fix: Pre-auth Android SDK code --- android/androidreleasenotes.md | 5 + android/androidtransactions.md | 181 +++++++++++++++++++++++++++++++++ docusaurus.config.js | 4 +- restapi/restobjects.md | 1 + 4 files changed, 189 insertions(+), 2 deletions(-) diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 4643aa7..ee09a33 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,11 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.1003.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). The pre-authorization feature refers to a process where a certain amount of funds is temporarily reserved or held from a customer's account before the actual payment transaction takes place. During the pre-authorization period the funds are reserved but not yet transferred from the cardholder's account to the merchant. + ## 7.1002.0 **Features**: diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 06a1447..4d04782 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -584,3 +584,184 @@ Invoked when the terminal finishes processing the transaction. | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth Increase + +`preAuthorizationIncrease` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `tipAmount`
*BigInteger* | Currency of the charge| +| `originalTransactionID` Required
*String* | Currency of the charge| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `tipAmount`
*BigInteger* | Currency of the charge| +| `originalTransactionID` Required
*String* | Currency of the charge| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth Reversal + +`preAuthorizationReversal` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 72869b8..43d4980 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -242,7 +242,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'restapi', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'restapi', routeBasePath: 'restapi', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -279,7 +279,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'android', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: './android', routeBasePath: 'android', sidebarPath: require.resolve('./sidebarsAndroid.js'), diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 67f68c5..0eff350 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -42,6 +42,7 @@ Possible Values: | `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | | `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `preAuth`
*String* | Sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | ## Financial Status{#financialStatus} From cc879322781fc7183e8062f6e618afdad0adc5d5 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 20 Jun 2023 16:20:36 +0200 Subject: [PATCH 054/115] Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine --- android/androiddevicemanagement.md | 15 +- android/androideventlisteners.md | 12 +- android/androidintegrationguide.md | 16 +- android/androidmigrationguide.md | 2 +- android/androidobjects.md | 10 +- android/androidreleasenotes.md | 4 +- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 412 ++++ .../androideventlisteners.md | 702 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 +++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1135 ++++++++++ .../androidreleasenotes.md | 248 ++ .../androidtransactions.md | 586 +++++ ...version-Android SDK 7.1002.0-sidebars.json | 8 + android_versions.json | 1 + javascript/javascriptobjects.md | 15 +- javascript/javascriptquickintegration.md | 96 +- javascript/javascriptterminalmanagement.md | 12 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 709 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 68 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 261 +++ .../javascripttransactiontypes.md | 474 ++++ .../javascriptobjects.md | 4 +- ...version-JavaScript SDK 7.0.0-sidebars.json | 8 + javascript_versions.json | 1 + restapi/restdownloads.md | 4 +- restapi/restendpoints.md | 12 +- restapi/restobjects.md | 12 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.14.0/restdownloads.md | 10 + .../version-REST API 2.14.0/restendpoints.md | 420 ++++ .../restintroduction.md | 50 + .../version-REST API 2.14.0/restobjects.md | 698 ++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 70 + .../version-REST API 2.14.0/restsandbox.md | 44 + .../version-REST API 2.14.0-sidebars.json | 8 + restapi_versions.json | 1 + ...ndpointRESTAPI.postman_collection.json.zip | Bin 0 -> 8793 bytes .../files/RESTAPI.postman_collection.json.zip | Bin 0 -> 8778 bytes .../getTransactionStatusEndpoint.drawio.png | Bin 97953 -> 99008 bytes windows/windowsdevicemanagement.md | 19 +- windows/windowsintegrationguide.md | 89 +- windows/windowsobjects.md | 19 +- windows/windowstransactions.md | 18 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 392 ++++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 574 +++++ .../windowsreleasenotes.md | 83 + .../windowstransactions.md | 564 +++++ .../version-Windows SDK 4.0.0-sidebars.json | 8 + windows_versions.json | 1 + 67 files changed, 11502 insertions(+), 138 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json create mode 100644 static/files/HandpointRESTAPI.postman_collection.json.zip create mode 100644 static/files/RESTAPI.postman_collection.json.zip create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index b9453e5..d9c1d01 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -371,13 +371,18 @@ The merchant should be notified about the update process. `getTransactionStatus` Method +**This functionality is only available for SmartPos devices (PAX).** + If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. -The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: -- AUTHORISED - Transaction was successful -- DECLINED - Transaction was declined -- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. -- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + **Parameters** diff --git a/android/androideventlisteners.md b/android/androideventlisteners.md index 93ffb87..d7c103c 100644 --- a/android/androideventlisteners.md +++ b/android/androideventlisteners.md @@ -671,30 +671,32 @@ this.api.registerEventsDelegate(eventHandlerInstance); Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. -**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. **Methods** -`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` | Parameter | Notes | | ----------- | ----------- | | `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| | `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| **Code example** ```java public final class EventHandler implements Events.TransactionStarted { + //If the transactionReference has NOT been included in the request, it will be empty. @Override -public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { // Notify the app user transaction has been started ... } - } // Remember to register the instance of this EventHandler: this.api.registerEventsDelegate(eventHandlerInstance); -``` \ No newline at end of file +``` diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index 647643a..1a43b1f 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -156,7 +156,7 @@ android.useAndroidX=true **3. Create a Java class** -Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: ```java package com.yourpackage.name; @@ -266,6 +266,14 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren // Use the currency of the country in which you will be deploying terminals } + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + @Override public void currentTransactionStatus(StatusInfo statusInfo, Device device) { if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { @@ -284,8 +292,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren @Override public void transactionResultReady(TransactionResult transactionResult, Device device) { // Pending TransactionResult objects will be received through this event if the EndOfTransaction - // event was not delivered during the transaction, for example because of a network issue - // For this sample app we are not going to implement this event + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus } public void disconnect(){ @@ -404,7 +412,7 @@ org.gradle.configureondemand = true **3. Create a Java class** -Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: ```java package com.yourpackage.name; diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 6d0b68f..47511b2 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -9,7 +9,7 @@ import TabItem from '@theme/TabItem'; # Migration from 6.X to 7.X{#1} The new version 7.X.X of our Android SDK introduces the following changes: 1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. -2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. diff --git a/android/androidobjects.md b/android/androidobjects.md index 8da6340..307db54 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -377,21 +377,23 @@ An enum representing different statuses of a finalized transaction **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the SDK couldn't get a response from the Gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the SDK has a retry mechanism that will attempt to get the transaction status several times (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method to directly query the Handpoint Gateway and know if the transaction was approved or declined.| +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| | `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. ## Handpoint Credentials{#43} diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 96800bc..1fe0760 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -15,7 +15,9 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1002.0 **Features**: -We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. ## 7.1001.0 **Features**: diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md new file mode 100644 index 0000000..1d6f08f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md @@ -0,0 +1,412 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md new file mode 100644 index 0000000..d7c103c --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md @@ -0,0 +1,702 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +

+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md new file mode 100644 index 0000000..307db54 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -0,0 +1,1135 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md new file mode 100644 index 0000000..1fe0760 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md @@ -0,0 +1,248 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md new file mode 100644 index 0000000..1e7a930 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md @@ -0,0 +1,586 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + diff --git a/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index b15cc1e..84cdd2f 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1002.0", "Android SDK 7.1001.0", "Android SDK 7.0.2", "Android SDK 7.0.1", diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index a789697..97ceefb 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| @@ -479,21 +479,24 @@ An enum representing different statuses for a completed transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](javascriptterminalmanagement.md#17) method to directly query the Handpoint gateway and know if the transaction was approved or declined.| +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| | `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + diff --git a/javascript/javascriptquickintegration.md b/javascript/javascriptquickintegration.md index f3e18ce..13a7870 100644 --- a/javascript/javascriptquickintegration.md +++ b/javascript/javascriptquickintegration.md @@ -17,9 +17,11 @@ The following example shows how you can integrate your web application with the 2) In the same directory, copy both handpoint.js and the code below in an html file. -3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example 0821032395-PAXA920. If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable environmentIsDevelopment to true otherwise change it to false. +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. -4)Open the html file in the browser and see the test transaction immediately. + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. **SIMPLE, FAST, and EASY** @@ -34,52 +36,70 @@ The following example shows how you can integrate your web application with the + ``` :::tip diff --git a/javascript/javascriptterminalmanagement.md b/javascript/javascriptterminalmanagement.md index 2b9c36d..e945802 100644 --- a/javascript/javascriptterminalmanagement.md +++ b/javascript/javascriptterminalmanagement.md @@ -227,11 +227,13 @@ Handpoint.update(CallbackFunction(stat){...}); If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. -The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: -- AUTHORISED - Transaction was successful -- DECLINED - Transaction was declined -- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. -- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. **Parameters** diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md index d2ef942..fecc2dc 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md @@ -119,8 +119,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | A URL containing the customer receipt in HTML format| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the device| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| -| `efttimestamp`
*BigString* | Time of the transaction| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| +| `efttimestamp`
*Date (Unix epoch) * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md index a0d00fe..7c0d32a 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md index 264317b..671f635 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md index 64f8953..5f508cd 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md new file mode 100644 index 0000000..afb4496 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md new file mode 100644 index 0000000..d06d62e --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md @@ -0,0 +1,709 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + + + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md new file mode 100644 index 0000000..13a7870 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md new file mode 100644 index 0000000..98c0f37 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..026fb77 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md @@ -0,0 +1,261 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| The status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md new file mode 100644 index 0000000..cff61b8 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md @@ -0,0 +1,474 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md index 264317b..671f635 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index aaaac31..e59fe57 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.0.0", "JavaScript SDK 6.3.0", "JavaScript SDK 6.2.1", "Javascript SDK 6.2.0", diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index 6dc465d..c3735b1 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/HandpointRESTAPI2023.postman_collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 8907897..49beb4a 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -336,10 +336,12 @@ Error example response (using invalid guid): The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: -- AUTHORISED - Transaction was successful -- DECLINED - Transaction was declined -- UNKNOWN (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. -- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. ![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) @@ -354,7 +356,7 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | Response | Response Code | | ----------- | ----------- | -| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNKNOWN` (NOT FOUND)| +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| | **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | **Code Example** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 6ba5438..72c4d8c 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -49,21 +49,25 @@ Possible Values: An enum representing different statuses of a completed transaction. -`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint to directly query the Handpoint gateway and know if the transaction was approved or declined.| + +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| | `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md new file mode 100644 index 0000000..c3735b1 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md new file mode 100644 index 0000000..e643506 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md @@ -0,0 +1,420 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +**Returns** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://cloud.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md new file mode 100644 index 0000000..4ca8dfd --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md new file mode 100644 index 0000000..5168406 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md @@ -0,0 +1,698 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} + +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md new file mode 100644 index 0000000..9880b1b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 0b040c0..53ad76d 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.14.0", "REST API 2.13.0", "REST API 2.12.0", "REST API 2.10.0", diff --git a/static/files/HandpointRESTAPI.postman_collection.json.zip b/static/files/HandpointRESTAPI.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..8ce6188d270f5743be620a9bc5ba77794dd33e95 GIT binary patch literal 8793 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 E14%&51poj5 literal 97953 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

MB9M(Un|#h>p;3Z?iHQkh_KXJ}JgIV9 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
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object.| +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| **Code example** @@ -384,15 +386,8 @@ The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a res this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); ``` -#### Events invoked - -**[*transactionResultReady*](windowsevents.md#11)** - -Invoked when the result of the getTransactionStatus request is available. -**** - **Returns** | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| Returns `true` or `false` if status has been requested| \ No newline at end of file +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index dabc7c4..c1b88c4 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -146,9 +146,9 @@ public void deviceDiscoveryFinished(List devices) { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("0821032395-PAXA920")) // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too @@ -166,11 +166,11 @@ Instead of discovering terminals you can also connect directly to one of them: ```csharp public void DirectConnect() { - Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); // new Device("name", "address", "port (optional)", ConnectionMethod); // The address always has to be written in UPPER CASE // It is the composition of the serial number and model ot the payment terminal. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 api.Connect(device); } ``` @@ -178,15 +178,26 @@ public void DirectConnect() **6. Add a method to take payments** ```csharp -public bool Pay() +public OperationStartResult Pay() { return api.Sale(new BigInteger(1000), Currency.EUR); // Let´s start our first transaction for 10 euros // The amount should always be in the minor unit of the currency } ``` - -**7. Add a method to disconnect from the card reader** + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** ```csharp public void Disconnect() @@ -195,7 +206,7 @@ public void Disconnect() } ``` -**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** ```csharp using System; @@ -233,7 +244,7 @@ namespace GettingStartedApp { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("0821032395-PAXA920")) { this.myDevice = device; api.Connect(this.myDevice); @@ -244,13 +255,20 @@ namespace GettingStartedApp public void DirectConnect() { - Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); api.Connect(device); } - public bool Pay() + public OperationStartResult Pay() { return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); } public void Disconnect() @@ -291,14 +309,16 @@ namespace GettingStartedApp **1. Create buttons and labels** - Go to your user interface (usually Form1.cs[Design]) - Select View > Toolbox -- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface - Select "button1" > Right-Click > Properties - Change the attribute "Name" from "button1" to "PayButton" - Change the attribute "text" from "button1" to "Pay Now" -- Change the attribute "Name" from "button2" to "ConnectButton" -- Change the attribute "text" from "button2" to "Connect To Card reader" -- Change the attribute "Name" from "button3" to "DisconnectButton" -- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" - Select View > Toolbox > Common Controls > Label - Change the attribute "Name" from "label1" to "ConnectionLabel" - Change the attribute "text" from "label1" to "Disconnected" @@ -342,7 +362,7 @@ class MyClass : Events.Required, Events.Status ``` **2. Referencing Myclass in Form1.cs and link methods to the user interface** -Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. ```csharp using System; @@ -363,6 +383,12 @@ namespace GettingStartedApp { my.Pay(); } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } } } ``` @@ -390,6 +416,12 @@ namespace GettingStartedApp my.Pay(); } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + private void ConnectButton_Click(object sender, EventArgs e) { //my.DiscoverDevices(); @@ -534,11 +566,18 @@ namespace GettingStartedApp api.Connect(device); } - public bool Pay() + public OperationStartResult Pay() { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) return api.Sale(new BigInteger(1000), Currency.EUR); } + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + public void Disconnect() { api.Disconnect(); @@ -619,6 +658,12 @@ namespace GettingStartedApp { my.Pay(); } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } private void ConnectButton_Click(object sender, EventArgs e) { @@ -681,7 +726,8 @@ Run the program by clicking the "play" button : 1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one 2. Click "Pay Now" 3. Follow the instructions on the card reader -4. When the transaction is finished, the receipts should be displayed in the webBrowsers +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference 5. Click on "Disconnect From Card Reader" to stop the connection with the card reader ## Bluetooth (HiLite) {#WinHiLiteIntegration} @@ -1053,6 +1099,11 @@ namespace GettingStartedApp { my.Pay(); } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } } } ``` diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index b53ca12..3e2db2c 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -59,8 +59,8 @@ An object holding information about the result of a transaction. | `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| | `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| | `tid`
*String* | Terminal Identifier| -| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| | `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| | `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| @@ -122,7 +122,7 @@ An object holding information about the result of a transaction. "statusMessage": "Approved or completed successfully", "tenderType": "CREDIT", "tid": "ACQUIRER_TID", - "tipAmount": 0, + "gratuityAmount": 0, "totalAmount": 100, "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", "tsi": "0000", @@ -133,7 +133,7 @@ An object holding information about the result of a transaction. "efttimestamp": 1615374961000, "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", "requestedAmount": 100, - "tipPercentage": 0, + "gratuityPercentage": 0, "recoveredTransaction": false } ``` @@ -378,21 +378,24 @@ An enum representing different final statuses of a transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. It means that the terminal couldn't get a response from the Handpoint gateway and therefore does not know the outcome of the transaction. This status is **VERY RARE** because the terminal has a retry mechanism that will attempt to get the transaction status several times from the gateway (up to 90s) before returning `UNDEFINED`. When you receive this status, you can use the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method to directly query the Handpoint gateway and know if the transaction was approved or declined.| +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| | `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| | `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN` (NOT FOUND)
| The `UNKNOWN` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNKNOWN` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `IN_PROGRESS`
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 3246f02..0d82746 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -60,7 +60,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -106,7 +106,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Sale Reversal @@ -152,7 +152,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund @@ -197,7 +197,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -245,7 +245,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Sale @@ -289,7 +289,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Refund @@ -330,7 +330,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Reversal @@ -367,7 +367,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Print Receipt @@ -527,7 +527,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md new file mode 100644 index 0000000..1f3a441 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md @@ -0,0 +1,392 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.UseDevice(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.UseDevice(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set parameter + +`SetParameter` Method + +Allows developers to optionally change several internal parameters of the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| +| `value` Required
*String* | New value of the parameter.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Changes the bluetooth name of card reader +api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md new file mode 100644 index 0000000..c1b88c4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void deviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032395-PAXA920")) + // Put the name of your device, it is the composition of: serial number - device model. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032395-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void deviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void deviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +

+
+
+

Windows SDK

+
+
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md new file mode 100644 index 0000000..3e2db2c --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md @@ -0,0 +1,574 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md new file mode 100644 index 0000000..c09f2df --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md @@ -0,0 +1,83 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md new file mode 100644 index 0000000..0d82746 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md @@ -0,0 +1,564 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Requiredv*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + diff --git a/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 543a0de..2c7a2a1 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.0.0", "Windows SDK 3.4.0", "Windows SDK 3.3.0", "Windows SDK 3.2.5", From 0ded217b1f9d434ae519fe5528ae85b844662839 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 20 Jun 2023 17:02:44 +0200 Subject: [PATCH 055/115] Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine --- android/androiddevicemanagement.md | 19 +- android/androideventlisteners.md | 12 +- android/androidintegrationguide.md | 16 +- android/androidmigrationguide.md | 2 +- android/androidobjects.md | 20 +- android/androidreleasenotes.md | 6 +- android/androidtransactions.md | 22 +- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 412 ++++ .../androideventlisteners.md | 702 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 +++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1135 ++++++++++ .../androidreleasenotes.md | 248 ++ .../androidtransactions.md | 586 +++++ ...version-Android SDK 7.1002.0-sidebars.json | 8 + android_versions.json | 1 + docusaurus.config.js | 4 +- javascript/javascriptobjects.md | 25 +- javascript/javascriptquickintegration.md | 96 +- javascript/javascriptreleasenotes.md | 11 +- javascript/javascriptterminalmanagement.md | 13 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptobjects.md | 4 +- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 709 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 68 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 261 +++ .../javascripttransactiontypes.md | 474 ++++ .../javascriptobjects.md | 4 +- ...version-JavaScript SDK 7.0.0-sidebars.json | 8 + javascript_versions.json | 1 + restapi/restdownloads.md | 4 +- restapi/restendpoints.md | 16 +- restapi/restobjects.md | 26 +- restapi/restreleasenotes.md | 6 +- .../version-REST API 2.10.0/restobjects.md | 4 +- .../version-REST API 2.12.0/restobjects.md | 4 +- .../version-REST API 2.13.0/restobjects.md | 4 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.14.0/restdownloads.md | 10 + .../version-REST API 2.14.0/restendpoints.md | 420 ++++ .../restintroduction.md | 50 + .../version-REST API 2.14.0/restobjects.md | 698 ++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 70 + .../version-REST API 2.14.0/restsandbox.md | 44 + .../version-REST API 2.6.0/restobjects.md | 4 +- .../version-REST API 2.7.1/restobjects.md | 4 +- .../version-REST API 2.14.0-sidebars.json | 8 + restapi_versions.json | 1 + ...ndpointRESTAPI.postman_collection.json.zip | Bin 0 -> 8793 bytes .../files/RESTAPI.postman_collection.json.zip | Bin 0 -> 8778 bytes .../getTransactionStatusEndpoint.drawio.png | Bin 97953 -> 99008 bytes windows/windowsdevicemanagement.md | 25 +- windows/windowsintegrationguide.md | 89 +- windows/windowsobjects.md | 29 +- windows/windowsreleasenotes.md | 11 +- windows/windowstransactions.md | 18 +- .../windowsobjects.md | 4 +- .../windowsobjects.md | 4 +- .../windowsobjects.md | 4 +- .../windowsobjects.md | 4 +- .../windowsobjects.md | 4 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 392 ++++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 574 +++++ .../windowsreleasenotes.md | 83 + .../windowstransactions.md | 564 +++++ .../version-Windows SDK 4.0.0-sidebars.json | 8 + windows_versions.json | 1 + 82 files changed, 11592 insertions(+), 203 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json create mode 100644 static/files/HandpointRESTAPI.postman_collection.json.zip create mode 100644 static/files/RESTAPI.postman_collection.json.zip create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index 53b4c1f..d9c1d01 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -367,19 +367,30 @@ The merchant should be notified about the update process. | ----------- | ----------- | | `Boolean`| `True` if the operation was successfully sent to device.| -## Get Transaction Status +## Get Transaction Status{#getTransactionStatus} `getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*String* | The reference of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + **Code example** diff --git a/android/androideventlisteners.md b/android/androideventlisteners.md index 93ffb87..d7c103c 100644 --- a/android/androideventlisteners.md +++ b/android/androideventlisteners.md @@ -671,30 +671,32 @@ this.api.registerEventsDelegate(eventHandlerInstance); Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. -**IMPORTANT NOTE**: This interface is only available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. **Methods** -`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency );` + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` | Parameter | Notes | | ----------- | ----------- | | `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| | `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| **Code example** ```java public final class EventHandler implements Events.TransactionStarted { + //If the transactionReference has NOT been included in the request, it will be empty. @Override -public void transactionStarted(TransactionType type, BigInteger amount, Currency currency) { +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { // Notify the app user transaction has been started ... } - } // Remember to register the instance of this EventHandler: this.api.registerEventsDelegate(eventHandlerInstance); -``` \ No newline at end of file +``` diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index 647643a..1a43b1f 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -156,7 +156,7 @@ android.useAndroidX=true **3. Create a Java class** -Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: ```java package com.yourpackage.name; @@ -266,6 +266,14 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren // Use the currency of the country in which you will be deploying terminals } + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + @Override public void currentTransactionStatus(StatusInfo statusInfo, Device device) { if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { @@ -284,8 +292,8 @@ public class HandpointDelegate implements Events.SmartposRequired, Events.Curren @Override public void transactionResultReady(TransactionResult transactionResult, Device device) { // Pending TransactionResult objects will be received through this event if the EndOfTransaction - // event was not delivered during the transaction, for example because of a network issue - // For this sample app we are not going to implement this event + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus } public void disconnect(){ @@ -404,7 +412,7 @@ org.gradle.configureondemand = true **3. Create a Java class** -Create a new java class called HandpointDelegate.java and include com.handpoint.api.* as a dependency: +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: ```java package com.yourpackage.name; diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 6d0b68f..47511b2 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -9,7 +9,7 @@ import TabItem from '@theme/TabItem'; # Migration from 6.X to 7.X{#1} The new version 7.X.X of our Android SDK introduces the following changes: 1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. -2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. 3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. diff --git a/android/androidobjects.md b/android/androidobjects.md index 6358f82..307db54 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -377,21 +377,23 @@ An enum representing different statuses of a finalized transaction **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. From Android SDK `7.1.0` we won't cancel transactions anymore and will use `getTxnStatus` to return the actual status of the transaction | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is applicable **only** to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. ## Handpoint Credentials{#43} @@ -655,7 +657,7 @@ options.setChannel(MoToChannel.TO); ``` -## Operation Start Result +## Operation Start Result {#OperationStartResult} `OperationStartResult` Object @@ -666,7 +668,7 @@ Object containing information about the financial operation being performed. | Parameter | Description | | ----------- | ----------- | | `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.1001.0** of the Android SDK.| +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| | `errorMessage`
*String* | Detailed reason for the transaction error. | diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index ee09a33..9fb2597 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -20,12 +20,14 @@ We are introducing a new transaction type called [Pre-Authorization](androidtran ## 7.1002.0 **Features**: -We are excited to announce the launch of a new feature: [**Get Transaction Status**](androiddevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](androidobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. ## 7.1001.0 **Features**: - We are introducing a new feature called [**Transaction Metadata**](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 4d04782..f571949 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -69,7 +69,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Sale And Tokenize Card{#3} @@ -131,7 +131,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -179,7 +179,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund{#5} @@ -226,7 +226,7 @@ Invoked when the terminal finishes processing the transaction | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund reversal{#6} @@ -273,7 +273,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Sale{#7} @@ -318,7 +318,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| @@ -365,7 +365,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| ## MoTo Reversal{#9} @@ -408,7 +408,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| ## Signature result @@ -450,7 +450,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -543,7 +543,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Card PAN{#13} @@ -582,7 +582,7 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md new file mode 100644 index 0000000..1d6f08f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md @@ -0,0 +1,412 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md new file mode 100644 index 0000000..d7c103c --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androideventlisteners.md @@ -0,0 +1,702 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`dendOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md new file mode 100644 index 0000000..307db54 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -0,0 +1,1135 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md new file mode 100644 index 0000000..1fe0760 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md @@ -0,0 +1,248 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md new file mode 100644 index 0000000..1e7a930 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidtransactions.md @@ -0,0 +1,586 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + diff --git a/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1002.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index b15cc1e..84cdd2f 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1002.0", "Android SDK 7.1001.0", "Android SDK 7.0.2", "Android SDK 7.0.1", diff --git a/docusaurus.config.js b/docusaurus.config.js index 43d4980..86ff891 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,7 +229,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), @@ -255,7 +255,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'windows', - includeCurrentVersion: false, // dev: Change to true + includeCurrentVersion: true, // dev: Change to true path: 'windows', routeBasePath: 'windows', sidebarPath: require.resolve('./sidebarsIos.js'), diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 138f50a..97ceefb 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| @@ -479,21 +479,24 @@ An enum representing different statuses for a completed transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + @@ -691,7 +694,7 @@ An object to store metadata. -## Operation Started Result +## Operation Start Result `OperationStartResult` Object @@ -701,5 +704,5 @@ Object containing information about the financial operation being performed. | Parameter | Description | | ----------- | ----------- | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation. `transactionReference` is populated from **v7.0.0** of the JavaScript SDK.| +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| | `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/javascript/javascriptquickintegration.md b/javascript/javascriptquickintegration.md index f3e18ce..13a7870 100644 --- a/javascript/javascriptquickintegration.md +++ b/javascript/javascriptquickintegration.md @@ -17,9 +17,11 @@ The following example shows how you can integrate your web application with the 2) In the same directory, copy both handpoint.js and the code below in an html file. -3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example 0821032395-PAXA920. If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable environmentIsDevelopment to true otherwise change it to false. +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. -4)Open the html file in the browser and see the test transaction immediately. + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. **SIMPLE, FAST, and EASY** @@ -34,52 +36,70 @@ The following example shows how you can integrate your web application with the + ``` :::tip diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index a218a57..98c0f37 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -12,17 +12,18 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 **BREAKING CHANGE:** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](javascriptterminalmanagement.md#17). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](javascriptobjects.md#transaction-reference) obtained when a new transaction has been started. +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. -When starting a new transaction (Sale, Refund,... ) the `OperationStartResult` object will contain two attributes: -- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. -- `transactionResult`: Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. ## 6.3.0 **Features**: -We are introducing a new feature called [**Transaction Metadata**](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. diff --git a/javascript/javascriptterminalmanagement.md b/javascript/javascriptterminalmanagement.md index d93ba92..e945802 100644 --- a/javascript/javascriptterminalmanagement.md +++ b/javascript/javascriptterminalmanagement.md @@ -224,9 +224,16 @@ Handpoint.update(CallbackFunction(stat){...}); `getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. **Parameters** @@ -234,7 +241,7 @@ The method accesses a transaction tracking system or database to obtain real-tim | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*string* | The `transactionReference` of the transaction to query.| +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| **Code example** diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md index 55f2960..fecc2dc 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptobjects.md @@ -119,8 +119,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | A URL containing the customer receipt in HTML format| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the device| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| -| `efttimestamp`
*String * | Time of the transaction| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| +| `efttimestamp`
*Date (Unix epoch) * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md index b9d047e..7c0d32a 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md index 3380930..671f635 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md index 067a170..5f508cd 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md new file mode 100644 index 0000000..afb4496 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md new file mode 100644 index 0000000..d06d62e --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptobjects.md @@ -0,0 +1,709 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + + + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md new file mode 100644 index 0000000..13a7870 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md new file mode 100644 index 0000000..98c0f37 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..026fb77 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md @@ -0,0 +1,261 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| The status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md new file mode 100644 index 0000000..cff61b8 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md @@ -0,0 +1,474 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md index 3380930..671f635 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index aaaac31..e59fe57 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.0.0", "JavaScript SDK 6.3.0", "JavaScript SDK 6.2.1", "Javascript SDK 6.2.0", diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index 6dc465d..c3735b1 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different operations such as initialize, ping device, sale, sale and tokenize, sale reversal, sale with partial approval, refund, refund reversal, print receipt, tokenize card and update terminal. +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/HandpointRESTAPI2023.postman_collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 4cf2725..49beb4a 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -333,7 +333,15 @@ Error example response (using invalid guid): ## /transactions/{transactionReference}/status -The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. To use this endpoint, you would make an HTTP GET request to the specified endpoint URL, replacing {transactionReference} with the actual transaction reference you want to query. +The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. ![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) @@ -342,14 +350,14 @@ The /transactions/{transactionReference}/status endpoint is a RESTful API endpoi | Parameter | Notes | | ----------- | ----------- | | `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction status. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | **Returns** | Response | Response Code | | ----------- | ----------- | -| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object). Here we have two possible scenarios:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. Consulting the [finStatus](restobjects.md#financialStatus) field we can know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the database. The Gateway has no record of that `transactionReference` (although it might change in the near future). The [finStatus](restobjects.md#financialStatus) received in this case will be UNKNOWN| -| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check the API Key used. | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | **Code Example** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 0eff350..92c230c 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -50,22 +50,24 @@ Possible Values: An enum representing different statuses of a completed transaction. -`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the API couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | + +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | -| `REFUNDED`
| The transaction has been refunded by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The`transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change.| +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. @@ -101,8 +103,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| @@ -136,7 +138,7 @@ An object holding information about the result of a transaction. | `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| | `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| | `cardHolderName`
*String * | Name of the cardholder| -| `transactionReference`
*String* | The `transactionReference` of the transaction to query| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| **Code example** @@ -237,7 +239,7 @@ An object to store information about the request sent to the payment terminal. | `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `transactionReference`
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))).| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| **Code example** diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 5338920..9880b1b 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -12,9 +12,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.14.0 **Features:** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus), allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. -***Please note**: When a transaction is started from the REST API, a `transactionReference` field is needed in the body of the [request](restobjects.md#transactionRequest) to be able to check the status of the transaction later. The value must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) for the transaction that you want to start. It helps to ensure consistency and avoid conflicts between concurrent requests. +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: ![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index 9a582a9..18a0706 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md index 936a39c..8665bc2 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md index dba056b..c96fff0 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md @@ -97,8 +97,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigInteger* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.14.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md new file mode 100644 index 0000000..c3735b1 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md new file mode 100644 index 0000000..e643506 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md @@ -0,0 +1,420 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +**Returns** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://cloud.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md new file mode 100644 index 0000000..4ca8dfd --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md new file mode 100644 index 0000000..5168406 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md @@ -0,0 +1,698 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} + +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md new file mode 100644 index 0000000..9880b1b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.14.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md index 733113e..f5d4857 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md @@ -86,8 +86,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | A URL containing the customer receipt in HTML format | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field | | `deviceStatus`
[*DeviceStatus*](#device-status) | Status of the device | -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid | -| `efttimestamp`
*Date* | Time of the transaction | +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid | +| `efttimestamp`
*BigString* | Time of the transaction | | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed. | | `errorMessage`
*String* | Detailed reason for the transaction error | | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation | diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md index c4edfba..a397551 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md @@ -98,8 +98,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*String * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date * | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString * | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String * | Detailed reason for the transaction error| | `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| diff --git a/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.14.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 0b040c0..53ad76d 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.14.0", "REST API 2.13.0", "REST API 2.12.0", "REST API 2.10.0", diff --git a/static/files/HandpointRESTAPI.postman_collection.json.zip b/static/files/HandpointRESTAPI.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..8ce6188d270f5743be620a9bc5ba77794dd33e95 GIT binary patch literal 8793 zcmcJVRZtyFkneE|?g3@{Wha>n*%4j^lL7jtFuHV2Tii=DAO&=h2AYi{ad4YFtZ;S93Z(!_v4j?RlRi}`2$8(lpE)bgQviD*8q61XoDRs$39mJ&pn;Ah*X#0`?rk7***8{>1q-((Y>g z%8<6KdXB3-$j>Z_=J39Vp`VlyV0lI~?G!zj=Xl+sr*clh~RM(_FB znkw#$T#7A`+(j+vn{>+2_*1^cp+sZz=bF2Ww^Jet z9@GX#LdkE?%i}Jf`#J1S5DpBA>&4${*Am_i;p||2mGSpW@Y)pNIk&gr?zqAuqS&?F zl|?xDBIB!E=(+r*-E0f3{3}E1yVsYTAw&dP#Zv*ZdT~-05*)+GWkzJiY z431hQ=9Y&%WNh+^v)^AN3oc}D!L^7V?j*UBjQ)x&c;ic6{M`?3dM*Wvy7(G~R(+H) zCegk(?(#+m!Di@uYpvJE&pzIF(}x^C24|2M< z3ExJYwex{kERGkrP+j{=K~<9rFI?kbLWA-R?Y`(IM(PVE`r8yS+Y^+QFS9 z$y?0^eZrgb^z(J&AVbg-E7_F>`1!cq^sIvSEtr$&mlKTIP1pHNUms7^6^Dlh`1YCe z&hFCC^}NW}@A6Gm{*2ti{pecn#5CyT zvjzwY$oRw`(Yb`>+Y0*S2T=FV%zfSGjeQ5^{nbhFiJ*1EYkgfT$rBZi-BMHN`jLMZ zN=%;Yw>wN8ORfHwe0|cRJ@3Fjo%20Nr?B_&16MJy-i&=^NM7RNDcT7lg^fSJ@se#6 zhkuK#JF`f^3J3qx0&m4-We$i4Yzduf$?6n&^J>4aeV?+D!?*=#G zvv(K@9K98V?2%nv;Ku ze4_d35BW{v!M)u;EeK#EtRutwb!jL*zEJMKgj*l9l@;O|r|W~56jx0X~c>t+6o z#~%`6(%i_-CE-5JJ=K%_xvOw_W^_NuBVd4fqaK>pB2W@Cr^&)z_vwoz8>pJw-+zpz zk`@nmpL=H;!fa)UgTvOO4#U|ycQ($WJGCiu;uV&_b4R_GUg3+6#>QVk^} zjZDSs>ksXHQ|H2i3OAf$fT1Ow@^<^I$EUR0A4PTTPM2HMUGxp*`5u zjD<~Wz}55WB*-m}Wwjn&bDkS>>2!Y0eg#~-x(9(rlOMq}nUvy1V0IhPPNbw>6e?eY z9Z2abyI&+~iLO-@OO>SCZ9L_4U;-XhQ0OnRN^iOHf36we6z(-ZeF+lQ|210_=K1Tj z!+`98X0Z9d39R)|BIGtM&D=b%{Um?KwLz0rf=9No7O5p$74((U#`}u98+JrEm#xU2 zSds_ydqWoa2gSH8eMD-M3SFr{x-*+(j~`YZPxRg4&*$gU^qr;*Cui_s{aq-xXGilz zGO_)7byn=29yMe3*BHRsfdD}iV8i5R-tB~)DTXXN6TMxJwm1I@II&~NsKuV5$Uzjo*hd>mx=Xhkhp2xEptA?#uxo~Q|6h_wt?e@;ld9_7I+OxV!8>OE*=|?mD4x!BS zW9c-Yvkq%$&^ZZ5wR;o}r97qM@bi-wdlcWc?E>cpg+Xmix_*`RGm9XCnXFuZ;xS(J zPO8?yAFfamY7CE6H~6VKJR86PX2vhfsz1sbeK^8mF3UNtazQd0Vr)0bt6uGwwaLmY z8cCDos%QxiBlk6rQ@KU+`;>YC+dWUjrb?>CU3(}3fcu)X-B=r}WU1#ZMn6iy=>a$+ zG2vNU9|1qGz(#9n_1acfrt~izWiKv_r^LJ%F=1){3E6V6lX2t+=`uy+5{xgUKtW?# z5OimkL4$tff&POD`QuW!>?FZ(7TTnKf)4_w`aI!V0@dZ_*&P|NV~(YCl`c)L#9vOX z^-TD-Oe(?|7?3d^0+%Ccr=m45k-4|r-9_j{YDcY|r1UUcg8?Gf%6&Ka3nWc(hUmmg zV_c0j%wH#R6H0pvIqOJ^-5HFRnJXl9!cyP>{0F<||%2QGs)%1WH<9B^Tj-QmFUyRfir&kkQ)r5IJ;>h!fb(jXq@(6k%wh^@LY46HS=Vt2Gkix}I{?w&k!l3_kBqo?z zW{|(-A~e&`!GGp!@vY|a)bYb2D{bcJZ8#0}M86wfCsHSQq?nk1rrNJt?@tFRw4X`S zq$;<@fR+Vk2u!3yoh8^;%|U9e0u_wRX4F_jWpULP&LWu|3o;`xoom=rvIe0fI(v9# z&O4>Qh%`N2tVm;>Px2k3_`XZ;KX0Koecr;_k24Cx9b}our{vRG2anIFIMu-+`LIjC zx-AwI)SGT*WqMu+k>Io}#Ua#^5P$PJgCqGEFjCHRLDuOH-qE`2> zW+%tKqFz4*QlY^0-uSh|tc{_crqmQ9NUXjob-R%=VY0Z@`^nT0hpORwt{W7}O~d9% zDJa*@n+I1PLLZ~F)MPvx@ivhk@%1U8c9Hmc0&^>mZETm74EBrmu(BpW=aT@*DYGb9 zv1Vwsz`5%h-Up2NyUXMp90c2j+C-|8m6!aTF3^p>%9gedK z$uPST)(ppeizf9<`GG@h?cJy1t1P4!Hz9`d*(#fa9i8$_80XgA$gf%pmQrPQlw|Vb z0*6o!>R>o_vSRT+5WZm>Q}?#DF!A;iOuwN9%0%K_K9Z}#?2p&2M1gj=^20KRnQ?zUV8$A(PN&Q71!y2Z zlN9tuibGa5S(JbmRtR25B)`=wp~;zJ*`QwJCe93xrc$ruld`|KfynsHi>)UMDD?bc z44WMM}RA^FXINcl+{&KN3ZUu>T*o3P~H^=_1;qqUfMsSq0-=`iH zVY2DaN;qEP(V?@om|!^!O0G7*UNT@CcM>97_4rm(&E>azbY#J1`1!8eOFcuQGhe#J zy*>+xte-J{YCNfXUy(D$#F8$AAR@1bcBVC+i=}1`^$yE+^$){WE4ai$VRWdXknCaa zlS1ayLt9!)V8iDjPAI0b5Ma73^mMI`iFFy@-Pn?ZGu4WML;xI-jq-&EsBg+$>Nrm+ z*jJ-I-j;p@ke_}%gxmJ(Z3yR{D-sl0=V+3Ts-nqbHV;Kt3vb{=S6+nTOg2Qz0wEc; zZIpuD&zi&ToXV53Bs*kRfuV)2jj)_Vb{s|xErOdHaG>f8Wm2j~nf&B4G?@TYKYk;! zVBRmq2|Ql`s>o&$H$v8FdV1usi#6_6EB++AeTPIS$rC{(R=unHJkfl+)v;W78 zUq!c9C$@fJcNixZ>$5J5ek^%ipC9&Skk!{STZdxdyWs391JeS6)f5^ju5zq10A!#6 zLPD78DsB=$j|4%q4%O$;(GZ<%Gqj6*P0kdf+hbX_-kN|jXO**1XrdM%ERm}N{G=bb z!U(SWn%{%TEVx?rM~<1_m?BU3*Lc2Ip8z;MhM7Sir~Seu`1?>*gyQM}$w0jeAwi>= z_uu1R$JoO@oGDXsh`v2!Z@Jt2+JpS4a1rGUtH+NA>$c&o5z1-KBJ?PZOQ8KG{y!RD z9VieJ2UQi#24El~Q)fbM=s_w%6YY6<^C)|kytnoFzi*=zj*H>kWP5((sY7TWQ?z5< z{Oe!H5{>#e)K*N#=HnqPOkG6Av@##D&oYlgz?B|jMJ&Rg9miTzvB4sd>7bLbkG z=%k4|)3*`Ff3D*~cDL>FG0xReO18K_)V4%ZvZoh;JRM3{(9`E@TWHl%_c2PHyLU?i zt8&1ixQ4S*?un4zX0f7`t)!H-I%6oFBn8XBaPuXfM9b2>LSES#)FmITphL^@@+gJA z@@6oDXWs#mNOdn$pgGC*seOshGOn*X72G&e%V;;DG8rZvKoH3tMyVhW$d!0)BfLyw%;ir-ntXg{pH8j{c+o57Lo`cah5gbWl{9Q@ue zJ&ixY5G^rfReLtm&p2#GEW!*dgIhBc6vX^Ham?$@w_oM`+e^$$1Cb6Shn24Ut z^D`ZtW0W*abXM=~Dlq@Z)t43X!INLG#i#sIsr)nv_N{7S*+fhAW81BsaRbGdF0rV; zle-)Z2UaYMsYk+gsHu(0RMbevOMjgwTrE)|kigW{Bb5~z;(J1_L;XbHkiz4&x79i4a$) zj$iA^k-7W$+S+=n+Wvqt%|HP|FU!~!KIkvB^6sCnkN!EHW}o`3<1{$An&yE`ICXG> zC#GSt~GMrF*C2)BMWX>HeKmB*%XHBak1ry()6PEJ=IpsPIu+C~tW-_8~OlXO4J zDME{gPY)Y~<#!Dj{!7TvpPF2%c67bBdxiPVNNK_y@~-dBjVP*S)B? zIgJBM*`ME_3E$UO?Ir-Bo0ts^LHV_(<=T1vTuNm;r4!#QRKIpXfg@_qx(dTn#_<~8 z3RZX2W(YC<_|Sd%R(N8jyBo#Q$F*@#gxJs?Hr08h^4| znT6=WcTH!tgu{}x&x3brDmTCOEoISKn9(x>J(~_qd2N;I$PnQe$d}ergEUu?zs{r> zJGIZ-hJIrsUSdg|_xZ)dxVwApw2CqWXBN~mA|=P^ETQrvIV<~j=y+gKUqfO-O=@); z1JO{!oOGoAxf8eWICW%*(cH{}IQVd~HV<%f+Iwjh)LfL6Wy(KPtl_1_Q`t&XaGFm> z6GsAw1})P2WWddSaO6$R3p-5OefGL^f2oaDZfBPN(XV+@r8l@2J!FmH0H591ZINAS zRTbr%!OWsKl;B}*16xMcd#o8oje5pmoMMFva1i(qKf!^UVN5bsHlIc@1d}?MxHY*j z)AB+!Q@?$_S7*ar2gBSJgo)8fbw4(++w5(;Z*XTVb49dna?fXhzJKThpYp;qW84d`0L->y2fP@;uh!(nX2*i9$t7yrBm*(DF^G=-zFAN$;Qn$zRo;K;n zxhc)Zf#`7jiYa>rO#tY+Hbt#|D*y-D&u}f?0p%k{4WA5R zcCD>4zZE!o;nNToe!co?y7m)c9(8+;v#fE6D?=pz9~Vod<*YkoZX_mKRRm3QNDkG< zk*Q)|H1SW$p;q=4NuAnF+%!}_=4^lYRCSl7>8?>Opjc3*feb0EeU znWxFB>z$6G?>g^rRVM}<50UUv9%_~h{oRD{8}pU?bb?*q7Pvr9I8F6#R>?E{jaN!| zqO8+y(9bd=p%YEO+HKcL>*meZknD>}MVYd6bSU+ysDOgW?z{ML{vyW2sG?zA8CE@l zpa?H-YLn;VUQ^)!-*^nLEU1>7d6%p1$WdfLM!&phRJXBai_cYjD#8t!XlDek_tUje zKkWUpkZ;m$Zn8XdgNkS+8JCR)q|{n?%H`}VN;5^+qu=sI zDN)L>i!S1x8&HGw9@{_t?q2;E?MkWKRvuL zK44Y-(4=?-y3UIYJoVB0*e|g-DBHjwNjKgq%4(rCOZSsU2g>)hvhj9$UXxoAHZujq zJ7Ry-TV2$l^Dnv=$u^?#@bG=SeU06Cd5ztN{CbD*igmtsdbtAY1vk!s_s6ntzVCBq z^Rr%^Z9WiJf5U$E)#~S!`we)$?;l}o9qt}5M_zX>;hu5_ zu1mjxp+Do^Yee=WVOU0n2w3MbPtUMc+a#|(h}`7ph=Fw?XIBlx5l`}pez-&4!JuQN z(u#d_Z-2%Pl^ly#qYcBqtztz-cX<_&Up*4cMTxfXv?&4`y_Oco-LX(sSKqEFQD^xM zyS&BDiE1J{z{ra4;6ds!e~FtTJQN^7H4)+Ys9@C7(B8o(iSH=VK=D|uw=(0!)_L#K zWx>LsP?Se9Wk}H3t|((JeU*0!uttHmN~DAjH1_w4YiJ!7xQq{d(&t{o=KihJcxB-f z3pDtahu%IBofEmW&oo{VaMN-$k{|>+D5w?Wm{eO{WC!~Fn44t6LT*h)vcFjCo7Bvq zA3IMPZhk;U2}nIM_`{VMuLS(LI-b&pnLC=?-t2@ zM5E6wyp5pHH=4q|hTgU=j`w)z^U29NFu~)YG5V!s3yfQsiv`LeSAIfJ!nsfkx+zFS z!9`*h<}C!85O3wLe{wX$e{S>eleP9I_7VWSDv za&@bG3|)d+O!Y0UEo@k{-1d=|>UXSQ)x^Jle5a0c&uE%lHG1XtAAfXy%O#r=Rv>+n zES+x8>3c`tIsf5)&N%-1v|j-QiWT|4096%{QG%R5g*=eM!2HV;sQ!<%!RkMRz?Xk$ z10WC}E~%oS%gzS;Ux5e7|1Wr8`klbk^1I3R3xJaL1(xXsk*9hiRGyoX_@f&X67DT-UCdjR_Kg;>1~da)||AxUsf@S5*b2B#GI<~lXx zUb{}Zg7QlFwuTJ8Jg@COfWh_E)ui3bkuz5+_PhmK~z-i-W#ju#6-?s&B`l$WE6s zpD_5sN^`42+?8dd|3x?1Vor|R3FHZ<%LQ&ysErgm!tyX9DD6(6qsyQCxp#Bct><^Jc0asXG-?dsyeyS>!`Sn)fT$ z?mFkQUzYWB#P@FCz*cCRDR(H7;^j7nX13 zQ>_=^YT4*cqW=R!ciDzu>&V-^bXNL$melT)zoYaK;VXGwsPCi`wCU#UZv@o;qx%$$9f2%ghCqm`IPPJzEYz0 z4F*-A#aC#ki>a&Pva=D@?xSX6kA!${+05;Yc8^hGlAy0>~mb9^e4S)CgdNzxTM*d15VEm8kwwqD>#zDYtq`T=<* z?;{xHBOAA6bb7JFASNU+%k`Fz`h+}NBXt^!+4%K-c=N@8^){BEP&Z%;(em|*c1Lsk zonQJyLvCRcZLe^yhUjI_K@{Pw{|(=c3+qFH{ZQ}v(tz7fc<5dx<=o_rTMACMTPY?L zF0cSEbZZ_lq2Lot=9OTt{V*5y4RLAn^eoitkMP!VK+WSV&0~iUU6bFe__9Xf!{{}a zjV_xo48J74x=_E4fQUhqP-$ORs)HcuR>8{CVoe#>41h;Zy1B1g)_*?Kvliu2;_RBw zY7rDl^2=ws#XI~3*W6$pqR8|(%wk@s)gOjH#NnU=$G#5d+CuYS;QBI zKs}JBmyoU+-~ODD5B(f33vfwt9%011ohiijr=wkCd#cir*DCK=*?&CIGQ2$dTgjV; zHEy88j~i);py2CRE+-13@p603Ax=4!4!R-J!UbxED{dhrt!QlP__o0k+KfjNAY7$x zLqhlg&b*5@^-^KO(JX${YoQ)cW7m<~Dl$#da?p#miix#KWMM{k)Im-bu~1GWMbz9O z$K76#rX3Qt3s=4&gzk{TW=vFFB`st*Df7l)Ri17ld!l7|Q{tppG{`@&JZ-IW6$X)DJsfbQI5*@wpySjO`>U7AOiffz zwh)Ov0K*9`v^*YV^h3Jm<2Ev-+JITOB@6L~g<%QS#YVmaUAnMq*qyz~ZIBmI6fXmu zq!cJ&^FCq}^cG2^L#u`A(?VT_1C%NdPsnj- z{S@}X8d`e zvJk9`o3DINDpq{*)Z01+%V&|fud(cGVnE86N0NHRbYzL{XTxR$4Geeg%q zw*9Z)_KIg}whgTKw9wd`M*@jAHeKa?LCmSi>nvPRVG7r;p8e$9+!ne;5}}S~ba+qS znuxhT4#KhHNKsa^0F3;Bj1RW)8L*hPgL!zbiMvE1jUhm<)(p`B zc+ZMj*PU7cnLDt81CVc_7x`QJ4Wprw(K!{6)M1-aE;e!)jB8ur1U22w@>@|3CJxn=5dumB>rS-)ur_YC*;MWviyag(tyr>{X}i^PfzFnY zix!Y*dDgvR8X~>>=V_cpB)sS)?NZep@-I{k)abGcL6d*z=l@9MeSIhFXRdSMy>A^Q zyieHcYTnvngcA>Q;CC0$(pjROe%x6cT!_G0Bg6)alF#4lvWj_2DW#omT0{tN4_2Oh z3|{Y}5aACZZ}H9jreT&ldfa_O|m#C^&~Cx5weUJdSd|( z$nib8Ei%<0W-2Xer7R6^gU5ncttZiuCcZd0q18~>%zB*qyUws$(?o;YT|5uUVsLVG zGm25DkDv?^jgB=3I`lygxR9b(9Td=EY$uQU{c`GP0M?a9E{3)u-?nztY||o5cfqp| zr#=dtB2z2$QB5sh)wLp?6|FzBb<;p~21i%b3_=T0QHn`44Ecwgi2mS`Ra)1YglcBm zzT?_l#do|sxZiwe&93S41&U)QGPH1u$4DC>FlZs>g*K^&W-2=4fin(GHyrq>;Q-A< z@N3#Zc{>k+!;N1#6f3E;>jUWgjLU3*+&VhP0td5lXHfRE5-AKZ8uO7ZQ)(4-73q-l zvIbgZqjvRVEN6Yzv>9N_!h49}lsCgG0fnxzy55j%?N7m)K?igz`mltz_82A+-KKK* zcc|2P?x}Cpa7RwbbqwW4)D-0Kuz%ecuSZNJYDinim)FaQ=m?T9&yq#9Z_?4uDBE|S zl!(ob*pg*_WW`8$HggSkPRpKgbP3q*0E>g2+63c`2hvwihL?MujL_jE!{`y}d=(%+ z$_9cU6T>;OUe2r+vVVr`tvq4<+EiyPmp9`u39;VaA;+G>_MHlASYD&W?`a`~cnu%7 z-y8D|w2mRdz6qp{MTy>XhynbFL5Hn8_7=*@U!r*5A(}f=>`N=oAcra)({9mvm10)! z@xKzI?YZ=HR&_<{NMuLNF{9Y!BuoHvg%pvg5!eQ%m|FLR2AO0mP>yPfzU}CqRwZ$@ zGxR2>ff{b>gbZ|r6rqHFrfps=)n%sVZ```5Du;t|;a6fr1_K7=m!^-g`&lE&r!%9l z=y*w!BuC+!fz~q|KK!|L^kcNKt`P5}xrPkJ9X9dgGGU&4Ld#S+*n<~qOxu#O*B@;b za2bDY;6_~6)s8x=y$tj7*95z6=PlHjano^G*6juEW%$IEBomG>1XZv~9>(iQH4`Ex zhB}f0Yd11*8UlwHE8Go(HsBKWi!x)x1=eyF@=8#Ok@VI_2x~>`a@$`);o5+b-t`Oe60iHva)Vfk#@hQ`o|U7&RT*zew%Q2ewIkAa!NKe*=XZ_E!&l** z1RDwus)H9pmg@=F$04sv84{I7lwf>40R?It5Vzb&B^X*(81c+NW?YMb+D=paSTC(_ z`63Ya;DR+Mq)S5UYpc16Py2kQ(evBl+Qemx0o)i-*ajUf%ryE3ag{@mJ_o%kYV)G1 ztrn5`S;}+_tBv-ASs^Eg-=cp`>r<#ix^yHYuHMN#=W&{1*5IhsBnV(@lVAJyJrbmD z5bRJMp@~s=A}N}C?K!A!&Wh3SBs-w(CYrqLSacm^8Bo$q=tQ~_r>KP_3UnVA0iWLH zaLyWtYR^sv$libcfp^~Zkb5-5ypGsc<{d(jhu0no;nYF<>&B#1KJtkErgk{ZmqBVf za^VfNDq&L9BJC&uIvfk0oJgkv)XpU%l4p(=YsHiX5h|Q5stqY<12!g#$NRr&Dp)#= zX*3=`$~VvF1#weh0Mjv^z3GOO&L@g$e|>Lk6eZwN4n0Wb?fndh*2WKkk<(9T3^VYK zIHCn;>P27@2;tsw+Ar;Ko38gpl+y7o*LL!$7mH=?GM`&h9AY3Fi%4k9Vj3LoT3J=X za8&aen?0+Q^Ju7a($N8h06*6i+&Sw)fzHFjge9C2b;*>@#S?L4^bVY%y(gahyB^Iq z$5C#HOkBpW?zspr%tI$H=0P1If-`ZAF`T4_1;|5IkFK!q+S`*Z^ARGHTat})fL=J( zUY6ksqifS4)w$3T_)~w`_#7H!c80UP8{RY`JjD23(nLwU8985=BT>2b$-OZ|e>O$gyoY;Op`uw>T}02H6O7f{w~O z=crS`pke%5OfhgN`)HI`@kU<6^dW1Uo$Rs8i$DO0Ts(1_JREkJ^FlB>Hgxr(sMtD% zLwPhN?v3VfYXlaotgQpz+?Z7$`-HG|VG;tYgm4hR_de91X)P`>%%HxjTOBhZ%b(3+ zbuVjUKv^8_cRu^|@$cQ2gt};g#bs4K?1i(gbEWl50yT8*gqnv;{;On*-y&72DhJyP z=A(GloV*$2_{BEESp1Geb#Lwuc$ExJT%5E%4-L% zH&MJN1&0Bai%9pw?8-5ME1Ok3w2$XLvdQWQ9Hq?)qXdb$_2v?~$lDOv;>tZ|GF zal_Hy+K5bXh@+_vlsikAb`qAPj0f}u2)(A-E|G+1f4U8Dq`SD#k7Sizrak{^iE|df zYBpYfpk$aD){XLq-1t3Cr^TdsAg$GRl^qV{>Gr4a+_im{Tv4C|y(G{GDG;eCIRTQP zL-sai1t3NR-h5b|z~v{$SnPX+%e;EgQE#=7vqQLH{rp`c8Kq(#qW5Ne)H!Q@2(9vG zrvb!x*&sEpp;Yo+-Y@Z5QhK);sc|;-~>v&H1+AH#A&m)pY4u6^?M0pJs>rteH`AfZ#lny@lA7 zSCGWe^%!a@p!2-CtsO+jb=t8KQRI##mKLIwvy1GNwfJpcBQR}kC`F;!iC6{fWU(1f z=clv=8w;sIxuf^g^i2fM)vsU8S@rE%F(A|EWWGiO#u7xx-P1d+#uK*|d;S(fC1(xl z__)0e75Ta`m!~)~7?PN3gA#U!le6-(pr{^29Q!sr%2k}H#jyGn z6l99zOP!%$Y|f;)s^yAFStdm+vDH5@PajF00BtM(Tu`uyD?%r-B=9a+Y2Y#GjuK%X zrXT{5^;LW+3&N^6q;soKbo(!MIKD@Pwi)S;mc;Aa$k3txzWcgXWXZ8~{o-6c55)JN zld_ng!~l?Pox6V9c<H1OGu@~I~u5;aPsSNgdWiDtrYl)J-KA%s2D z*d;<38XELd2*s?7kR;rjxk=eb6(q=%*9r>}&(c0y6?=m7^`Fj&R za}1`Skk+@kf+4s`Mnl zX#OJLdzFYpaS3ZR8Rxo9e8@uG;8@ZHl>@Jf@U&%4PW6L#AvW;rCziLg`GmgnUlgrS=k5H@Z!F`Qy!{g%FRY?JlG(_OD%7}@b?sxqq z*~~wJF{S#rQ^A>W8|s|OCCX^i?a|Pp1G;YrOqFQ*sApFm0b16-XkrDJLL$;fuou!w zwYqJ*GH|W7xqx?^-}8)Gey6@CV`rIiw>J#@IX6CFsNwWE4~?d4F8m30KmmGFj7gQmu2Nnhodu`z*rEA7Qv7ZbZ z0gXXWj)i467q7u~D*B#emxpZktl9P6dMuwYB+auHZd6jyX_1{A<0~CE+*RPVJ&8Cg z6PVal$#r&4Atoo97&X>Rq)j63*{AlDy~NZL7)<%_@@8an_~M4_)IT-wg6cG)&ML9JFP4nxCts!WwLS_{Q$MdVTN6p$3gg3;NG2ji#JRLD$Ebb4!plm zeQp<<7A2qp21q36jbE*3W`ON+Lxi>-B*X|XNQn^bd`FrtYlV{EQ>p$WCS(48eLH#W zq0FTF+XZ2aVONqgRiV)9)g{qm1g`}}9#(9aO$NdNLb zPb!oY_-l;{WRm@(Xp=U{bIaw;p`xPE8OZT9*xcCcQ6QoR$2eobvhu}9ep^H$JYNOE z60o@nq&rFa3ZL|R?--pS7YzFk_dROL?9+QZ!YnQtq@yH7<{oVw*c{>d569_8I%h^F zh{eE-6U)@7G%Bs*^11@(R^*leTU4{=dKO{I0XA)cY{^1rEYV_QMsvVDu-C(*jDhn( zI7NT>=oas7DT>Qf9c{vzOa}{2sqF zjW(^mcdvp-pK{${1`_(9+wd&OzektQwwz&+a7Q;WlcEVy%hKsoKKq`Hr9VCDAX#Jl z-b9cRvREJd!^J0VQp~-}rJP4M5pDL)TDz-qTB(um^=B%h<3Mvpb>YxFwh}FL#I1QZ z&Bni*5D!ySthJUc60AV&O4-Lthn`xOXgQJgY3*2 zzb&Uc_oRc1AC84=f^?bx^zUQomk{?1jSAZ3%aNf0cc~p`_MDU`qaw>bsfUmdDIk`i z7K1Yn6d85_);C8#P6Jj3KMe}ZG`_;RDa!Tw^%OBJ6O`($Xa4W#h^BV7Vc&Ba5?`Nn z*yA}d;_Mw&2daditwLG2P-Ytf@cmbiH7~&K;0i7*!TB} z1fJf%KB$DE-d@M{YwkCP=cAxdYgoFwzHTzRzizT{Z*retMxM4bYA$75k3b)1z8@pq zSGjAQp1-HLQe#^#YoeY*KrVi7pI%_FjFA4wQ{T48+H(1If08u9&)twAf0F?hB%$^C z>IXbsa&6W;YqojRy!F}aUH4W*ZSQPI`U!!_c^Br^)i1AK8rl!Pos6?Wb2 zu5AF&E)Q7-S1iR(C-aqCXYGiDxPMhQ1f5;tVHE1mkI23I5Gdo+S>Avzm*4@JAU{D$ z0|J^4H`L>gU6(qIC;bz>W%uA0g>YRTh@FbQhrV4Ok1(aL6(WEL98&%bzzL^L4su+` zh2J24-G?O^aGXx}pYnUVUQ_UXJBYdZKI+a)(vR@mJ5BhUyKSh2 zvQ_E$Z0Paz82UIllN-F?t~dnn}SotwS!CWC>R+Z_M(Lq{VJ>wc%|u3swGpAN!T zD$e&FL%46d_$c&V28lvvL7SpF%1{V*`ik}fRitKE@l8p<53X;@u6GePbh0Pd@m1HL zr?i<1d`C`SqnnoW#YlAGi@(#YoZ4Js+uD4(XFO>IH~vC zi-z~I`|~V%hrlmK`xEQ1fA(E@g0&+w_fr7V?o?232;pv!EmSJlA0N-i-W0iTI@uxh zpVO4v;;4!F1!C~njH@^*Pg{Cgk!g{UY43m1SlHG@nF2KFysp!h$M2kZY} z1N8rp2YPyP!XgSPnk>wE{~HJars)5H5RCM(jm-27^{?e*)vr<2!xjA@;_x78&)^;_2=ARv&%#e@_fAfS?ge|p#8fEI~T z7ZczQq^*Le07P!v?FFFeot?0%ow<{Nu^AYGlv(imCsHN`BTHL5Qf47iCMIDsu%4Zb zr3LU2Xg9aiH#RT^>wmw;#K6Q%%fLp<$fm@|PRh&=bOC;`(6KYKsDJMdG6Y+kPb6*W zVr*sxB4rX`rDFi5qL2pZ8C%#{+8U8E3jo*R7It7W;4jb&{FYS&eyIZg7#Xw~S+&_I zfsg!FR%T!ou&$)B-PtV6>~zd*Kr@A;n3A*zP`f4bis&Ino(h z0^OMy=~%w4D`;e6X%2J}VPs^YW1wSYV`QacVqgI}|9n&t;2~J)7=boLkO9cX_|kG` zrvSDC8Gb(jLq-!dOGOt}8$&r+Crbk<6X^%`-=Ew8Y-4K-9NV`;yjc8fu${9N_iI!lVrRz`e8onFaNYL54OUbKt`G{GbI{6$ETqm@S1sw37NR>R=f=d*|=V zSb%_M`L>1}aMrZImVZ0j#hm6&qBbBaBWX+hZ-=b!^nDN`3p4QKXWPR)h{(D8oQh?#|UipY@DIJu|C-Le75gRc9xcAcE(n}ZPc^0umF(sn~oqG8%xLE zb~CUvJAdZ$Rjq)>`puxT21PxP+3#CbjP>mRFrA^6gNgn7Ue0=pfsGA~E>>n_C)B-^YJzx=fYt=Xi0NHkOvae3yuJ`SwL8b0%ht~Mg3h*%#^z=q3t(n}i;q&qXO}{ZK$D>v$o33K0Q(61pySzvjitSX{x^B` z?UpInPVWpN-!9H)6amDNprx6m%{S6Bi--ub2?_#3Ev*0nWp~CF9B17x@bo9gdVc%> z``dvpnCxumAEV_bW<yr;{_}HwUEBp##I=; z0>T&FE;jMM8p3DfKSRJJ43jdkfy}J{Kv?M7p8b)L{k7$Hzy|9BO8Hz^TiO6DU}$Lp zG86vU`img`*+wj90#2oe}ly>K9J?3*3#YvP)y%!iYxnZe4oz_WMc?EH!-g4 z$9T>)X9x9tx^E4CEQT(G+$9Oe#9#w91B8pi#Gj4+bED#~7K!HvatTfs zBJoWAi2M#Ywt#bC3cfJi&cx6qnggo*o3U)}1Q^6tMsx;dmX3NxAR9Y6eXySKcl%nv z(a6{itOzLUvms?{y|rF4=EC4Y4y7bQR4m(H*2~YiVY02j;iYJC_G%gFrv8 zSb)plBj+Dt^}mqnObq7)ydXO}Af>(?$R!1L72#RWyZ!sH^ZAA@(fvD(g)Q{0ECKiZ zcXYlm&H(~lBIv)?!~tXy0|&67@0IAH{R`U+}_K+Eub#-jR8C8!Zon4 z{N_3TeFE}A2KE|;KqAq_7>k&TUx>0c=%uY?ri@BP645mUDI zdU{|WR`Fj{eV4|6q1pu^!r$loLsVVFE&iQQrE4lAE$<*`0b(*^QZls=b`jBMy@(86 zQoRq(3@#v4av40AY%Dfw`?Ij5fUc#DKG=pcUHqc!#ezrkeqBx7pCL|$eHObgz2A&&L2ZB^!UHt zuK@BlzXTtIKz2Zmh=KoHN-{`+oWXz&KI?VKoA~>!Odz~$V|VUUFfjvM@E;vnW4@4f zm$30)!}EK9{g2J*e<)adwUq#1_!k)e8;8xl1<~ZdHpakV0Sx$$#L~{0{7++PKo0ra z0bLHJU44@OzXa1RPUMmeAa4);mK;+0nNkBpqvCne42Z?pfsD<5pFaB!Rj?QOqr$MNsyhHkQ@WrlVio_jpa8M?oBz+spMGSLnHVnE|00Y28~#6+ z36})`<3-T-D(m`>ZH>ztIorj5Lw8J9%CmC=>Jq$vFUf>}DDSTUJ2BAz7_I(0vriXX zb#*4=r?NduK>ok=JFh&bzc7OB^gUa7;YXZv#TjDHY}w09aRpEOOA}dFp3H?U`m?a; zpJ0RkePP#gBK~z|^EvzcC#9gTq%kA&@6;e56aKAB8h%zWr~&+TmhAlNOB$}g)78g! z-tkY}u=9xhe?Fcr5+FY-8-K-^#2pkHh$9Fm8DGI=e00VU;UC-8SxBc2PDzc5$I zd{NVJ#!JAturU6}t6#F|85z!H=VeFtXT;<}$o*6ENa_Yx6m?wG1z)1=zp=Xg3uEhl zt5J7utNp2rx?tV^BpG!zVlHBdKaIM-O-AV%0WX(*3ml!xqYDA^Q+Qn^eV7=4_vV0i zoBk_>F1^~qdXeDx6Df2>XyGCt@oyx9&ei*WWf0TV;kyg-{<0AIL*D#P5<>E9+JdT# z{LCiSCieO!97-$(QXE&5_yEG>H-UVNpIoQova&u=BV zoaXv=_u_kyzTY?>aQ0PI-@i-+l5fir0)h}iT!>%ENo!dXR#iz2&x2o10uAQ9eX#wC zh30$UN6*~zy+*L+le53hzOf9KE8N{EPiy9zdh|A-~k;LnnyKdX3S#Gy*E&0Cd4icx$Om!jnGtBem1Wx8# zEJivVjGx{X#L#Q&u8w`6&?uqV>v+!X%p?+uA6)B)nr6@%$M{BOZt12dKp+RFy)`14 z1dc~M?gu){0|mIe9^54sqt_iB9oN|v>Bg%({a(K|-Qzwz-W{jVuB=dHSIm$Jw(sY4 z+w-zp=n^hXCV8V;psV`U2p!jtKHFx#gQzD@1w2;hgF&DV-&aa(2|7$I3|A zjW5m7h?apQN#luuSkxxL?6}UOBE9W zyI=wb%0E`&Je{)|O|9~zs)|=8i5o#fLxVr3Es={{sdlP9XnL{t^$Qon=KA(_*_=Dz zq^v$`P33GQgzd%NAp8EZvCOUviD-!&$p}WO#TYtGfwlzB_4&>;iY1G&3eHmJI5zWJ z2fM5EZ0fI6F(afSoB_J7(Iwq?#m1siLR$(O*N`UNC=WJqTL<5NK6Sf^hm;365GglX zI?)_an7s{Ns|hbTB5@KmF%`gGQxRWYxw3e3Omr}>o zu^J(KWnN zRW%MRU3Oq5t0R9rUPE_5KNKw6CVNKfDWMcQK-}#6**966WcQDZa5wK85R_VQ&?i`8 z*n}jS0z5r@Yk2Oy-FrgLO2<{Lz1`69e)q$j$EXp3Rw2mKaFWt={ z@2fY2p0oZsQszBidpy&Yh)1oGi|O89VzIsF6rn5*BZUn}bZG|@{ZCWSP+RuXl5vZe z(X7(Kn)@Umx$6jo+NlzqzHVBjR*)o!EGm&6-+(doX6OZlK$7;B;wl1I89Na7v8j-aP|>-W~z3qO5MZ$MRi z#JgnRP7+6RJ!R(9aSj&EIvULvRM zE5bq&agys>^`t2zkPH2J$%MUiiOB`4E5q+_JQc-oh7EYd@+G1uh#J`u$d!3?TlW(f zKu`_Ac;pA-3eKk|?(3d$>x0E`@lf^FGccg#B3BQU09q{JA+#r%<%CJjjz zY3gF?!~oLHV-_8zi$~V1>hTWn%!S)yRAnACNyA6C*Z3j^v5AElb*&B*=#_3{>4@2g z3bfnv)x^_l^Du^*1>vEdBzr{GMaKJ1e+mscvDNIDx#O&9qbG87xBs)VzlmmHvUEHf z)`0xB%37*GQ*lO?dz*0X!?MRvGT!Yqr<;cdp9nntk$qn66E}SslGA=?=iJHS=@y=y zM_xW+RkV4yT7}q~7*Aor=D)qY)L%av@s%*H&)m)FYZH$IjK>*SJ+b+nJyV7GoFAb> z)Z0nchn(0*5Z#=ZyhW897g*k;g0ms6cmkXaYzncn9Q!9KGJ(pDeVe-=;&2lFS5x9I z!GLu0W|2>vkxbf+B$UG<-dAXOb3JQzd+Yda6JeQnJlh*W0TKc?kfJyVC}mM3lD6r! zuDW)qRSKaGiI@^fZ|m1Zo@6C>(coL8{#~(*dXE)Ere4K1rY(|-V=J>~Yb#yTu5cpK zI=D@LC@LV+l^MoEr4%Uf+Ja13YB(VckQ4spvBa^{x>e%%MscKNlNFH@7@`q$+0`WY zBqm%A%V>D$7#tA{acR!?=K=#+*pceupafDSTjt|4WBal^6mF(BXNA#zVYW|} zJqh-BO2WBJjl~+0d_2RC*H%{IVdEa=WFo@>pr@{BfTm5Mb-WO`k^?1s`-rKaCxxg>73Bv zi)Ya6fKjr~(qtT-7)XDOf+RQ_PrFSrh7OBf|A1wKRJuzDx>$t3yqC zZ=)%OI{-GCoQgW!9TICpoYhar-&e?bqWV!Py@Wh@@*KswBKm5F0v>QpQ;Up z6emYWv4IE{3KV)uW=z#jvP^P+aUddH0amdw=bl6OoLZurjUJ!9%rTGei%ukIPu;e6 zuRLr*#CSO8lpdE=&T~oiMps4VQ*WZ}ABx4mVX*nSDUi;>5!+0vn-Aot5Lz{tD|c?L*|M;OAzZpdP|L_E-~Tg@!l53H~#Zq>G% zQM_4HSo!vihB(jk=Sc0HO+)ms8Q@pcF1ZOzW`1~r+!sX|=_-$7^@LO~aEQE1o8tBX zfeEQ&Mt74*9F*9ieXvPzwzSg;$a*R5H?lmg2@)kMIYh-U$sQ`Kq);ZziigCUB$K$2 z+}<+0J4sSD8DOK!*G-W(85IA@C2kL^`*mtycBJe4gk21^(#hT&RkeKtcrCXv2esLhYl(S)GHDLL=hjK!y7D1*+-@kD zM;O*R0`KjoXC-aQ9Emdx&^0lBs`uzrYS|~WPDdpSz#fH|@8W}!ERL`h9@)RSq^MHb z+eF^FN)lfe>+zZF7+3u|Ttf1-*|O z%0OlAH9mNOVR-OngDb_&P~54w6^9*dv6+07f~8eke z<*)AaF z1iB=kq^B^k_Vo|r*)6dROiLt*8#pH<6NH|@Joh!w^N`sNUn%NnX?2)Sg!_0uimK|Z{r`n+%`S^)`A{Au-1Ve+kzgflm9#*8>$#iB>liYt0|L{#$x7n^)K%^_hVA?YP$e?X&03oKO6&o)n*vxN@h}z^s-=`EuCQ45%kd~? zB6(_+w8WRAi}|_dnOmUQ!~032C8f6&j)P4qIb}zxDK=YAtd8Xwd;54IaWj)0$kD%u z1mG4}F{hYU66a}@WSF1q-B;{mh}Mo!k8r>aNyf$yM(BNOu|L{}y+P^0O9Wmeh2kX! zT-=9P7?Ae~`Mkx8sH7uVSZ@`|L4ps53U@kanmpv4gT;x^Q*;|~>}QbJw)XE@ch1}p z^X9Yph*MdvjX(VAdUKU=AcA%-%hnf$4jfsK! z#GQD(N68;DfQZpQi!;iEa+MTiako%Yr9-JbjlLJ56eUKmhr~AQcfx zS>anKrkjsYrjgt|dWx!@-o4G}BwYBnfeXSDBEDpo2I0P!vAzqjFwgx^oXXkgt}7#+ zG!mZ&a4rHIr)U#IyyZ3X3V@FaOX?i_OK{`?%+zDIoz-z!eYk)i8=Y~UnToQ&@(5(k;lC`;2ACUBrh>nW`)5apNRn-k&uDTfeuIky5DOWu*i7uVd*h3c zEra__PcayzCx8rs^HFCb`R&=CF#+_YIlsl#1c4cR_-XMXzJ=L--UT8>zm33Q{7sRf zx?7K4eOFS*pz*p>Fv^z{bewSrK%Y()pu(!EG?JaU{#51awMn#!N?l+f)HxHSHd966{!Y#wtB90#-K? z6=E$iodJ7vzf7aXD}AayS)gJsGCqUPzAG$Pe8X7mEm#8s(w%T^o!ROb zW#TJjY1!%FDo$_J2_&N>KTbX6Y%x>`n^)0|i3o-5=@tU=7h)cS(%Az&6swF3Q1n%! z_1%{2Ycy+Qm5(cNhKO2Plz2}oM`>H%=on5SY1op-#;f6$`Z1c)vC!aZ3*Mi=Sq@oE z2_(jbTjL_EgijGOPC^-cbDc=Eu%Fr{zi1vZpTh7Ts)nV7%9N^nD;o3AIzjFJFLG<94K3R_VYA)>dA~447gqv@0imxn! zN|!3AiE!f1REVU9t2O-^H&pErBr}GL?Es0jki)P-qluzam~`d9z8=`3oPIZx4;e}M z!=5tlSEor&toBN+$DaP=XxLO9IW1;k{n1G0)9MD$cPH3OC*I+l!XzMT zM?Q?9Ybqr2GdE6u*PNjqDXwJNJwhX1@raUzMyMD?aHPI!6>4>Ap&!xeaEIHC*5>|+ zfhPXTm0Q)EkeQniZVmBYD7oS&&^g>8Ih>G6-A}9FbHNHPbYTf?$*M`Q!kS^l60ciX zLoTmK!;=vZRJS7UZQa~khAVZ4)A|4>lMGo2f4nP4yGAXSaZ9e??ZVc5^c@n0Woo*E zm3rYScP~x^LyUBZXPRhj%Ox+vo62=k`M%g!({dlW@S}CMk0(Kbi1>^sBnEp$Dc{58 zGZjf=a>Oa;}7-6y~@jd;vlWRE_RPfgqR%C?Kh zdq$82i<`f)Hy1D(tc9a;RQ^4>zTv#4 z*Qrs8cadFHSU#nb0Z~s`aqb%PgZ}G$*ja?{)n|&$?m0gHP z48^rayc1q6vOaG$2e8%-f=`#fJ|b_|p4$KX&gu9oG>@B&&moSilk;KC>TBLgSlCA( zLLjmiMq{inFgQf$D`>-!VJ9@yL)RF^Lt6-L^3pB@^Hbq(gw=1MPY|W5K9UacTo-# z$4dur7*nSx9gLh75~k!G8$%(BkiLH)02?jrdF|mYZ(thF>$>t53l$NH#G7vr=kp%H zD0Ihr4GSQ+&pK-5)GzKN%GbSeskoU4JQr)})q(Q?0dM}moC@^_xHkyPZ8 z`>!$Dg|_Jf4C^@bn?Ir)x!Oc#u-Ass6(e5%^4TX9b~9C}z}w0}!i}+BNCd zk{u+iME;n0eE$$k+UBlC+h+v1bUkyW<8$V*I7KkQuA0y56VE_M{0aTIC#GuYb%u8^ zajdX#s6C!|>u(wcZ6B?0d3CJvjkocA*egn72WQ^*=AH2BC$2zrenK+)AT!?J?b>P- z>Fl+UP0lAi$z*p)SkM+C^+iW9-6!idiF@%zYTk5 zaUpF{NdA*_o;$~ebGa2llf`q??c0YRhw9SgfJD{fm(Ht`ipxB9w+~ObeHj{>nVCf~ z5GA81HLsHf;)qVxz^+S%+;&+SjLeX=o^GIhSZM=0NB>YrY|W8hs1@yr3oBKM{7QCX zyoTq>!kg)UlvHFcuWc^nK*RnvzL>TEP)~WV^%p9gda7usp0^d!r6}}p$+;t6i z;H?g7de`zfzcfD+F3wh7bA1^o24pT0c4vp*S?(?M7~kgdfbvY{!omOgN_RomsQWG5 z^^<2@ZHI(-dpM71UA=lWlmh3%KJs-pV8k_ETONRIiF>2K$5jlY&K8AR5A|pj^hos- zOvB?_!H<7Pl^N-RNz*z#jxeZ-bid7VAO991W(PbEdDuO1k++hZkk1e(aGf4PJ9T`< za;!}BRV<`2N(3=RXf!%y7u1ii58R0#+j;WoT?~beuwz(K!5gZ!Rpwj!ZhLF!ZJMS2 zbcy#Kqi!7gp$?R}(%&mF^#PJt@N^~Dc6^2NwG*Jz+Tq4LkDh*6a-5i0XPzPqh%RQ0 zV>5pG1c*~Bl1;y~aXmgj-dP^@yTj#3#6ZY*dn;417^=M3G|-L-I+!P>I@DhC1MJg; zRN|x?pP+lw7Zj-{K7~N*HDq0zj|%52s6)3@NJg~Em_y=5DG#t?+wY*O#fWSdN^dW~ zOQkcAQ9msqA3Gecr+)_9*|UHu$bz>z%rW;4+VI$cNF0OuZR=Z@g^1%oV0FE@ucOxx z5cogOw#vUYuvgX4sO|1Xl#I!%u9u8iH%%JBWild6c+QH9_7zP1Ah)60uw6dIjdN>d z^aeJzyy)l52Sq3$$s9K!YjuT#behuls}Bd(UXcq3K*_h2FgBC2O9zF2 zY|4mSvK_?r**HDms zoG~QrjK;CeHQseeg?JfuaGALcBUX;{rur)@D>;VIvBjmUF{lR#c2}jfU!YxddCli zfIsmdn8ApT7n4run%*fpByAjfeLBLa;IsiPV997cC18gW4Z*MHJstTJ{2FI+dOGOH zH;7pF>&X0AG2$z!_>e+yv(Cwgnmk=cbFWFN&ZDC}y?He2QI*p?Tpk;ilGOoNPXbha zr)g8?i9?(nH(c6>&lc}(3GplilCfj@M7FEsjlZzxTFEHrdMO>WqQPbaOH~;r`$Qs+ z%@ejwtDLB(4akJ08tz(%#j^!B(L%ixB;awYivWMN22h;h{fu4>xAxF6IwfxFzMh^T zM2rR0%g+#-221aE9&3zyeGC;#8@s3lsP^6DYZ9n_3_@^BaJfB5TIIeMG#S-G+d(!x zMc}qDGBUzwe}FVnX^Zpab2Jvc3%;E`r}YNC*-!-*|F};_y8K-hvlsUuYOdkE?$50a z=MAl?AA}t(cMwVOmiMdSbUcA-R?fK%(!a@+E;>3?%xHUnIWR=_)F*W7{qWwacTNkZ z7X8;rR~DD7*>1=vCs$TgQ|*HIBGNOLyKqQvYXp8ozRiuv&p%$^G|9bwI7KSS2XnPVEBTGPJJ1e!fQ4if_+%>)0O};)=FZuK~Gq$A`H`eYluNB%h9&5eIDt&%I z0e{-7R>pi!-Y9B3MiaOu^3$EFg0$L4_uXe{sFbtt$J(M__cQ1ZSf%7V$a{cgYuGB( z93>;*dp!PFe4yN&D?#y|-cVFPrbY&vL3<)h^AJc^+w672tCM{8%qJJJI2Q5d0}L(-$3XKK&s=`YdpO4V+FE&=ArA(&M7F(LCWCG}G z=VS>cmyJTL1ziHrqzmUEA-{NqOPc7kQYouTso4p78Qw@Fi868gq-1fKd+mm=j*A>8>87i{t7|Vkh1bsOV zLmGl_=}hXXJiWEao5BYR1EVwaRISu`1*6dL^Q&SY1n0KBT;Sis59PX>>?v0)VlI`$ zfq&PJJfXEtGx;vZnl&-n#_@QJM~(DpW-U{XQ`XK~erfI}GrQ33R^V$f-S1IsDXq5GhCs>t)}s9>eH@cPUo zZ)5m!}NH*U^=$SiZO|&!jH>wHEsCEH8**B2kq|21ex*P_#xku{S6g})Q1jrGL+LKg*p7!+ zF<7@Lq&PePvhismNTPw5>+M4GU%mu4DP~Lp6$t{ccbGHb7yF-9c`%gc=5c&zt3@>G z)P#|3$hpZ^R%ku+&^za7)wVheM4ZV~LI<6oK+*_W)RTMv!C-pwohilQ08+04@0=&yBGUE_4EAouAq|N#8i793SsG1C=5$pJV8-caiZA{N!w9@VSV;K4-RtQ-5bd z#6vAt$`QwIO01Rres}qXhn*xgy?;lN0MFfcW^p8&xn|NKgzMKa3?3XDtv~0qTO&-V zD_kCYPk@L`i=8d+b6{U!bnzy-}rH zG#@SWCA`k^(qW#L*9pe z-Ir6pUzG89gTwrQhP&L8yu#Qb;hw!&=x3GOnvY|Uh;!}e$@0;564BW2a<#E-U%m-* zi>MQ((_qWR0m>k}g#{ivA0Gu=Gi~IVY14op7^|qOYf`jc*Z}8f6e&FCE`h4v5keL1voA)E`EdfVzaxs zE2EBH4G!vWEyyvuqCdy@I~WDT^5{9hxb5xceN3`)AH*H^Iqn!)N7a{ouxI#6CU5sv zw423HAr?F;0i-nV;+Of!FOQE>m1G)M(TL;LuA%^Dd4SU#4+LkS{K7F zh$o+D3`dT}%MMW`VyGxhocHF@H;x{ly|a9XKFfcQ;kb})6P_B!Y;h!1;k1EPfx7oa#lb~5@peSBxx57!#UBGQn5Vo;8KWq$58zTaG63F1_~SEcR>%xSiD? zjF+E@gaa{g+4RwjZl(?`E$qm@&Ickl&_UWPB36wmk**7PhloXO?wDh~m3+c6Nfavs zU;Vz0RM-ParGDWjTMGrowdw_JVpHYY%Xj$qTeeL-TAs7sfk(ab5hs*h*FB%1&HkWe zFg1ZdD`U@%syV|i1HRm0)fdQEA$}>cJmsG_q_-(^U5fL6H=1g%Q2>}3t$~lA4+3}H z+sBS|^z?!UnKOch=`<_76~NTh_ML7t>J^x~Uq`Oxg)HTZPmAo)uIA~wd${bXyE#lw zkw#H!BY?)C*LGI8f>*4TLzB4!I#?sr?ZK-1YuFyo3n_pcB;uC zMh~i<@MKFrw7=F{NU|K&^42$CYK$6+U?G%NQUu<7@SeBcOecM=2!i63pPtqJkz zK$w}E!S1K?5^6#lHMfUT=MjF~>P`#AZzB8L+-u6YxOqI$@X#z|N)cQR=J89+#{)Fq z?@k;<2Tk^GSVaiTzC{*|Y|kicgLb>m=)7nL!sm70h|ToIdj+U9ocKE!RXJ*f*T%cu z;Za@ywq2>`E*UnB9acYOAW8pdCgXIz-jacJSabJ^5AKcrFu~>?0irLeMr4}b)! z<~5e$?kq`1>uhbcS|wLrkAug=zO0`_?cF;uwZ^s5O57bW^BIwG_|n4L0rNPdlw9veGPEF|89f_pTQ& zzfXN3T?ehwNxS}duk5vkrIW97io;?!#f03PACbdSrv}9u^|P`ko+5<}G@g`-8Su(R z79#UFW!9V66`sdXBsq4+94>oa11)xoLz>sr15qj5qsj*5P`W6wOo@}(Eykc)_a7?u zTaNH;tJ_=8=1o)CyYD=-h6uEvl8$>PaN<^l5V5?pbu(^2 z&U#e;^E0g1&*-s^=O)YB?r>e}kD7fmR5QKlI@z2O?8as^BBjR#=wqym4OD`Wpc#iI zUn(k6?i`RH+?se=oGIvdGlRd&9z%Ozk?Ym`T|al`_i^41pY z(C*EE3Aq<4c}epRmW(xjU1WCU?+4g1l|CYR71x?mG>!9KI`a>km^&*^7Vg|8#t;P@P6 z%)B$m*Tvm}I z-Z}cJiIL}3HFFIuUH3+c1wY8=YFM~51mDCuF+4CeI3$(b+upKIVwU|<)w0z`;wW`3 zZA*B4JRR{`uT0!%S(bv-)E4ype8+cdS!C8L-Ig!rxn%3|)C-i>VAb!u4VN`vS(Ae6 z)vPy+o^hHhp_Oky);=!3%X2W!e3KmwVBjLp@r~A|#Vy>~u(TIlwpZ}koMpTsmD#o$3t5{js$8~jsoBibIS9PXp%eJR~vVQDV2RQ`6s_FKsy@r`Gna2}jn@Pb(!HHt=%WD}WR7#-{ZV_&< z+s2E|w>RVTZa2h0iv~Tgs2MVc48+BuPY*|&xhots9&2T5=B04xf2`?XW+|hdm5e*d;^{<<@<_DnC*Dsl7qX?qdf9o` zFG!G|J5gq%nSqT)=?Ti$;k#e^Ujao?FQ2p6aB+tTlSac!MG4@*Mrdg^Ykv*0TKG(c z`7SqvY6qd83HuH<;;2hCdkfAT<~JhhuOB~eP$NoKB$s`Pg5u+OGC3@mY`~=FM`tLm}-S#mYz~7Z_R^kv<<#~Ld+!Mp2>0&)E+`mCKQ6lCzZ}be~z9#XL7hT06dmf|lFW?6z)_FP9 zz`~(4L#VIncdeP$q1aWTsU9#irO>z!-o}4K-_f_=*%-UUYwE{%&s1rn%z25elunbV zL3&&^2@|iQ3NY1aQm_z#qF=#=*1CnD{?2S=Q)?>v0<43NW@8lySdv&DbJoi#Ap(%^ zGLBKRd&x5^Welt2NkyU6Exh2ehs?B)#)rdXPsDYwzGpxiU4`lrSd5>hlT35}Kz~&4 zDIM-xXFei#VZ>Puwt3;H3B%Xk_z#WKmqnpGaS*N=@3OApO$ z&W^&*-!r;xw!G|1`KgD%&AK3e-cKRJLvZhKU#C7{og%8e^nGS2ZkpDjohJ11eK@$T(`JT^tr$DSG!-_cwQU180Gwg64XYgsYb zilD~q7rYUn-@O^^MyFkN3y3f^Odh}QEO$3NVzfgO@b(d2ZjYA4x$9`53^CnUj~Uh8 zsW>~`-i_0lrAQu*LS2CU#8B;n3#*9|jj#CKL-Gf>srZf=kkwr5I)fO5aYy|a)vAP6 zOKcq<$iv29Ro^tjC#rsyct^B%dk3Gkt6h*yW2G;xE-;kw)A7*~*vy?BBCDk}NvZzmyBFx!k_%BCk-%_%dTtDk-)kXUX>z6sGfRVx~T z9)OujwPAof3+HxfrS@`?{K`1xZj*R0<{~^gvI+4=_^n+?e|2y6O=bbhkLRR=W{V@$X}V zjEbTxBgpcDO=h~gKf^1>+d)RCPIR2OizWKo+A{B&uefYK3e&kgUWO4uDK)%>6-obO zEcZ>{!)Te!n(_4^@^DmX{3CyH1Y~4bPvT?=@SUxd?ycR}9{SvuR0`z@RHL&6kC!B0 zA=26M*bBW-Lxa=jg^DM!j_hJDR1miJKY7L|P1KUGhJ>BW<9<)`3HEBlvnxf+-3!<|=#^7~&DgBX%?EMuZxNt`&-MwF9=Vo5&m+2x+6qN3dnF9@?zd4;g)d zrR>4;x%=5Q%Tm5U(U>RAKJX}BF)=Y>7S%O-FLrjC!bduV(d3^{2W2zp;h?qxue%`o zz%R;u!bD=7)PM=jHGed)v2)?9`HC4aEDNC zs-(L42FBJNjRaI6-C{yAY)@!tJkjjPl<5@;5lNq9t~4yl^@>Ea+R6ti%nBWVEW_l& zwdYyhs2_r2=%)L*%NX@Ls;!EU2}G9I%rH{`#O0B7A&Sgxq@-g!9pTWM>CKVX%-C0O zTOv+Ynr)RZxGg;>#DTJ-rZ|f?%X)IS6+mH2ztqF2rSt)NViL|wJKSj69nKe4w=cs% zETRtE^Jqh_(j>9q=~PXl1lFe9JCknw`XC%E{t9-BA!3^@4=UY$8L|cHqJ!ib%`s!3W&{NQQ2MYR8G%P5-?>9hlDP~p?s(+6a&(Q6k(m` zHOk-P+AL+JGf(lPmEv+-K_B$3sQA!PVXTOL8g0#t^(7J%8Y>*si6q7lU6b$?$Sd&2 zj=X-5^^}!5Ce1aEhq#SqdW6Y-seBtx7|JK{y@L;47XIk_z-#D7C=9od`imm$KtKS4 zSm%DXlT6Y*)iY9bZ zT)he0^XLH$it_l;EHG6lP*Psg*Y-f{^M`Ur-?X%}KI>cYZrLceMyq2x(`t$g=Uo-1 z6y1^PnXJ3?m1vYz@wo%Jt=qLBNBtnHW?+cFl+V7D;M3!Ih(B6&cdCTZYHelMvA%Y; zu``Vrf}w$8AGcp_DFoAqoeaWcv0 zP<&o&b0IpoyUA~cAY}2OKN~;{GJVR(3mrRHL_dO*9EB$oE^N8gjlGzb(y0GP=n?;T z)Xa~%S@zJw7AUq{ypQp>?L8|z+4^MCm~Pe-06 zmR&Y4zs+@iVl#*~Fa7?maWcT_Y&2&^uZv8wm zwf4f$rvL6nRL_IBPO6Q^Y~e;>Fw3J=+GzeL zE5m_=yLt`5p;mXgY1k}>NFFw2#P#M%n<`};y_ZwKp;4#t?&|(z(RoznZM8gBBnuOi z5dqFDoV1s%Sg(527ovxuoWIX?l3~^1cyoiZhkukMn?{HxyvYzq>cFZg_Q55yk~ot5 zAKu<7sIF+~8Vw!@uEE_sxNY2JSf+#$GoAlQcB1b25QSa8<_2<{Gd<(&Vk`X9ck z`*Q0(Qbod zaT(SQNtGhWJGm^HxRFn(LcZK4m{uDeioF|0T=rjJ5YR+Nsi&A^lSXL~$)Co4%29Rx z+?=e?{X16nNfWf#BD>p5?Oy*>G_EDFdCvzKp0{1Vi2l)?5D^*p!_h;lj@gC+0$i}9 zh9}oURad*6obI0xB0c#bjY;cSsD9az?HdRxwBDY3Jf^vxKo2!at$2I>h{t-Rl>BSe zG?9?0SA_sYwB)}8g5&AVTP;~y)#!yjQ3$sum~f671%`pBjFKriZ|Za;orD!18QvhZl;*HN? zg|k#UUr@6`H?CJa!tC!JA_bU7jrkJ?3dgdxE-hX$d9jfFN()B7gpmyF-{KV!TCYsc zjD_>VS*smT=DKY7H?s^hi)5WHs*iNpdntvF=|-O;JBF_CSTI@PlczY#W`kIfA5|}U z6|rzA>CcNq-GiypZZ4?j+Kt{wBV#_!wOsTh_4m{milklgD=Lb$9~k!V9bXxS3Zl+W zvpKB6wrJ9RpvuWM>bm~(Gm`~-8ikN&7pSsRL<;Pu7pnjjayI940#~lhsBH1U|kypst1eXFR=6@kfdm=;84}s-?=OlHYWy}|?r>2Bl@+ISM&vELMn)Ca49=-gF$Aq$o2NyrD3Qz&RW zywBMTe}OV&C_%Xrht%KS(tiLooe-xhc3UBu6v*gaEdtm~5 z_OH{aTeiAzaqP45V+|+^D$znxz{U2yx6g1Z4UWN*FR z=R8qkc$PrdK)chD_!;K8e**94H~DV-)6@H+Xcnv5$0hH&v%ZIJcB?++R8|djEp5zK z_tiTXMjn{T)psvX;rlZK_Wy$gNJwvAe~ioAdd<<}b-g`vzHGHz_fg0K$)l?jolD9= zc&Vki{QcVQ)Gbm>hVW1A3m5>d$+GKkH8$woLs0Rr9^$)!z^DtLcpmEd97Br+_h62T zpR6)?9Pm6PE~fasZ&a<^)oKd;p%Nf^4UP^j>lDhF=M#*J30Gu$U-q8#>uq2&QKiUUNpgUtGu6cjh>d#8=yNhAPknGGu8cLrozOkc3^?nsIo|VdzXUx;- z4DGJsj6J_xgyB7GMjXu1Er^z18z7EXz?DJ8zt7<-|CbL1`~5;tSE*^4Y;!+hQkQ2C z=0sHWR=-qLtK8NtUa53c+TT|I%NPm#Q7u_T^p|T5n6KXTl)!pmQt8OxEmDB)bN`9r zAz~~NN^~2p&qTY1yA?f5quyi}huNe8apN}c-f63}dzE(n=}8>T%N>Ib&2;Ir^Hk$f z0DrKlb>p{7u>GtStS)>~l{iJR-iBmxzPqX=ldJFU9DWo!MFkSbxUoH}I@vjEAiCfi z@}wKxI62Z%sZhty&zQCP^ckSAs&Z8-cj?1k%D$OR=K)GigM}{k-N(537pxP#BeCCJdCD&ucYNC6fTk8u-i8cE9w6Qa-N;TpG0K z*Pj>$N$MuuO$EA_w{*5<9SsBU0A;LwI!+ekNx~a$^FgyfWp{{Ol@aH16px9+*;&i& zVN8S5{ui85c%_tb5fW;8v0mB`&0TkI`;GW;v!lM?$3E$ zQlrxw0`4Kek-{=XilWU^Xx;}Tm8s5GX;4bJT-}E)b=u*D-yMb0xc_)L#-`1F;z|UU zr(aJ1bhPrVaz?>CT||a*Swc6UGnjp#$iNT<%R0D}i1**7^-3tVt*^ENsQY{OY>q8NVXJrC2Ov zd$%}Wd_Q=K{pQ*y%QYd7tLY*3pxE$KO;^}07WrJ$e9Y85lLsrXSwR@SyC`@9U zyoXgR1!{LY{g}JiDRtrlKtph4a5JzBM^OjdJAi(jOGbg+e!S`IcO`~a{Nf+*X#tr# zvLryX@xH|at>i7n^y`7=EJD`HCNZojtr8?=NdE9bMa z!{yp?*%dfJ4D+hnKW|0u;}CE<(&(qtwUwqXC4<`tlSJyK$5I%zl(wTKC}iMr&ouQS zQpHY;IzNANR@}ZyFnw1q^h>U%Z=b&su_1n;QcaKO>vwC>S^g(EMr2X)C(LC{`XsY%wNFCYF4&Yq`6tf9}C%Wi4_=EDrS$Nv3=Ml(KP zb00u@A*ss0QI=Z(Wp7L%4=~EiE~Th(?!0>HiC{!*dX$%Dd`PwQ{J3(g)ID073dU3% zM6OB%J8G8Na-6lB+5)tD>FfHetaB^P5!#oiRw;tHAGG@NAICizQ8}+R z+s8VuvA61j1&?`u>^BCc1GME5y6 zuBqMi=K)Qkm!kpG%weEOCO3MZ#a=Unu4rfE+3WizV7<=?g`aF2U*Z^99ojoe8#1DX z8($7IgGrC=9k>il6)s!-UObpKTL{K6vvj^PoaoJnB0`^_%6D9N%)PmzT*cMH|U&<)X(C2fN>Y-t{l-(Rx%xX40`hzl(2?sIc;tT;;b$XjC*P-EKLq7VIeyqDNtX_{_>ZM2GOSs#pLkGeu$zP zr3K5Xx$K8zhr0ebZrw3a+6002+$kWJJs8OTTXfueDN{d@b?QD0`i*{v>syS^+5{>K z1qQ1Neb+Kr{EF8nt4*TiZr?)D$P{aVaw2AV!p>v9zI3-0=;&U-pwpDk<7Am~glUu( zE$v*HbP?a^SZ;*GvC2z1K4MEo8$|>2D46mLorlTe=t_J=%fSWIx=ii;i^~p2LzP5M z0m93JHS8qOP4{podFM(5_<~ZS2wF zkAg-Jiw}$L>v^gH^M@YE2$|c zqg`#-PV+ZL*}RncBjp?>4~AQe@tXY4P zh|Yj!j8vYgA=US;9C4(=}mu z$p*A*J(Uz;7vP4{a_*-)Me-w=T#PcDHVk|o&s62=RoD)%nr6vUkei2C1&}Omz14U$ zMj-O+-*&OOUKk-yCqt~|R4=rNR4T|dPPUL0NQp>*X#{bUDd(#l^3$0d=#&ic zQUo_W6cWDEfLV}DDQsG=`z#z1I%}06;Gr1Ses47ep)^=&5H_bT2>c|@suC8xhRRd) zuVH7V>2c3rEsAeW5{~?d)Icip;7^=gXcwt-L%N%h!qwN<0}Lg3iNcJo9C@M z%1{zOd}KQ9tcbsV@CV~sXvDfJ7l|Z_YeaBZ_{|m1Px9TPg}^(3m{e%YDwt?`rZw~d z&M`T+BZYuhN@#%YRkP)7u+&HJqGl7%ZBDm_tOT;zIGJ~PMKziT5v$yP(9c|cmg)8v(ECD4Zhe$ zi?GRtv&v|NADby>?ZU-z7Z16LRB?9a@dLz7m8xaYJ-if#Q_h-I7$@FiyUAo@(3^Jq zTzl>_pS|!tyD$XQG6fYY1s+uIXwR8DUzY8;v8uM9OC{WkXAkVedmLVBP>k@^6P~QK zjZ&cz4RTMGR9#`FogsPNsJ|r~U5ttSRf3sC5PYyS##?*m z%eu1QjX;dWnn3t%qy6NRO=e*ONj)a@IgygC>2`J>H5bPUhpmKKRvy7 zLrHoL`lN(v+N?fj;w3Ea#1j;NwjOK6-QQicu(Oa{)5_seQYD<>5_YP&E(Y3I0bWI^ zw!+M?v`~Hz3;isip2laSKHD?yuJ_I9tjxN^lXg;3kefxD)+E+Kdkwm^A`U!in_#Mi2i60)ydW|3*h3| z>jLpO%hkAQ`!9Cy4^y;Dn9*(FiTK~~{>VPDn1O*lH40jBhq_|h+JYyGx=?cbYr^SM zW*Vg@>=o`Wx*98=IK%Jqr*-i|qHWr=e^gk>1?B$eLQy3TRCDdNBA7R`NCJ%4|2uiH z$SJ(z&)8xJ?{+hW_laFzz{*9qy{?^Jth;`J4_6XS;$gf)g+q_X#R}4t^<32=n-~T9 zZ(X32pz;Cj_LJxr`Xn&s)DtN1d$a)|c5|hf+cSz1XtTpV=BoohOvx@W-3+`(fAs~b zn$z{Zc$GaLv;2H~9`bBcSVS;C5Uq5BcMs(Xrpkl)d-~-YkLD4?zPR}9%kdW1@Fgr=y9Ymm|<|_zr#X5S8r4G zs;RZOvdj>2&5TUW)2}Ww5+k48FDK8d{ZV_nP)PX=|A9hKTpEXALSrt3N21gG&BqWE(c9GYf=ia*hhJzBDV=c#@9 zogV#>SSSatZ-$~#rPgW}xSQCgwyy6pYg2s|WE>n?As}9D#=+NOVrFiHHnYDRjgQOy zL>ide6{(cNA2lr%)yOtC3kagA6qwR05R{E|P{zQ+-jYD+FG8jLc&A1yA9)?t6RFZO ziX~EgD+06on{Hvz`C27`Vd)tb=*){JFzK18Q*+ceoXts=ip&-(VBV?rnnZU4wf&f% zB61$M0mY#fW~h#t6nH2}Cz&%>5X;{|3x<3bEwD6I z!VmGdFP#~A7-#J}HvI0!S16MNtx(a6^6{$Cx6OZGJ@6G#3-qlh@~{klB@vXX;53ms zS}X%X3&@NWFhodX)zO(#oLMbxVT>aT^J9oZfb$<729t)(O*E*^41V16FBSngZTJUO zg$(r$O&Y@fwk(bx(Dd{3Q~tlZ_N-vj5Rto!Pa9Sr995IwF{YP23tK$!!5-`{hh>Dn z(@TenM-|pGf^PG@*f%^6Z}w{4_bjcv8Zngv*)5c^B$ELGIC2uGn9~58;REzoLs#sY z=p~=!-1{VU#?LB`y;ELsJ}Rn{wiJ++$AU!gpYa8^QVDY4kMU3h;6mWpffmdffWVvQ z$)J_9PmynUfd7mkzxIT9Q|~ZTG-92zSt`zKRECsslQ0IF)lBjGOl%_$o-l`tUd~x; z=M^x!{ds7Ltp28>5a-v0*b;)`$lAyrU5p$1&`+WxVgL$_GLPAx6#*c+< zK0Pyz+>-d8k0XAQP~2raI)#TPGG6(zfPJay#YZY9UCGvUX0Tl}Ey*7!`0)-G6 z0A-c3T$OrxRNWf3YRk{*_@BPd;a*F_B+`A#Th{{Y7QOYCoQsqR^h`lUER1 zD^SHwdXnejY1(rg9k)D3_6u9NU03e;;|XjHxslh36&4FDkp%bZFY6?ec$J9qD8I|; zB)~ZpdcG%ueM{7}J59gUEY$tXCgU|?efyf&6Cr?yBbx5GE;$m85>rABp0o!jeHUx{ z+i(pBP;5Eh)P(~bH*n@TV$1hcdq!Kx#RDAKTwL#b?o_-8A2D&V+Y4e-90S7H$swGr z94Hm8a#qhy$JQ5h@%A2Cv=9!fDV)(yrI;3@**b|+Ba$jCX#o3IS={cf6A~D6|g#VEZBMzVnUAr-AM)MkP#GR z#jbgz?fj9?6R*r1vAQsoY%DGbxIa+geb@^RU50wP(|FMIJenaqHCj`Q_5)oDgsq=R z_wxTl@>gXJFZ#wH+(C~GD5II;;#RJOHm;(Qfj2sqYCLYhbJ*REzfFP=?oRW?ui6e~ z2i-hWX%fDx3*T@^s@}xn4qI(H8fWdhX;aloo>jCP+ihc?2xW0QNoL&=OMc{`P9Dzh zm+qm$RLA{>XK+yq@O0Q;`TYq1Iw8!&FF`6mH0U2g!;9b^X!aO0Xe5K1I6mJ8nm8oW zG-9(TAUzbSE*D(|*6NkXP|JT+r+kPl7Y5iq57!s~#I)ZyUHtAK_fBTp+ zRozRX{rsK%i+I=f)?Lz(Tqc(YsF;rXssN$T-L4~(bWY|KD}5w{@rIeIsg@QItcT;7 z${!1W1s#^tL4NYLxXfDGuhyv)M*p^qmFp_YSnvF@Vb;HzdyeuLR6e?zpHX?r!s`<3 zzQ<4f@GP6UdWRqEn_%?aq(59`2;pheQsK`nK$S5Alody^I6f>eXWD*xiN+(w_-p0a z^Ap-Qqw2H8u4J=fc}gGzCL9^2?~6uPuIkMkzfilN)wasCJGQ%hxNRA{q(B^i*2V5} z6pR$#RDd7VRDuOV_;rZ7lxZP?@6_|0FV0i;Rsfg^*8XedJ3oK_?fu{J1;a`Q>-&HT znO>mj-z)sqZmJ4)u6EKVL4-xYW=hYx@7AeeIAY3QBj1;*I&O%;A3*~RM8u!Qj?R%X zpmz5|Ce&Pd5TrmFbulwH(*OE zt{0&*VYfCerw@aoA{OK5KA7cB8f=v34@r8D3g>h4H%f`vjl<=|yk4r+|7OMA`Ts)m zQvOhR#Hc1*uYu9-#&VWLsnCHdRKlr_Fq@tXd_;CT2IL!{SGb^7xVfyaE-Gumn?|N- zPi$mS)PIZdL;P-4q+yj&ubi{5hkxb@{owsJDfUS&OfARHax7H^cD~9`9w&hA)59L( zLr~DWY+i3UbZ{=WQM;|=Jrwn$-k;GF0q6=rh9CA&rkuW=Y zyKE)-Ft=dj!A7%pRW*e{bkB?N{vm#Hk|S~Dlf0iEKm4JSvNqX5d&1EE^xepjGRnyK#!SvkY&GbWNd^n~ zO~mK$CnTx;`5wn53&EP-txns&Dh9mDFEoOac2YFSRNy9{ZhdH~-<%3x?z0L_lfbGM68}gx8AWOR<*oLJ)3Gp%t^*lEDU# z1sP>HGZYWVnNB8P|c{fFKf5b;dKYap%i4Xn{ld3b)hm-a~v&vY$J zVx-yNU%?CcbSS$8XnNwH!C7-_>YQMhc%SONo1R@6$8YcspIZ9ZZLWJeZG3Lg&ZQTa zbb3UNqB;-0`}x3k_7638ZauwFMr&(Gx<^b#5p(AZyi!M5(__tpuRs zSSq8+6WHD6pP)c@Y~fJ=-2F{rQOKGGroTZ$Bm-9I-TMmY0{mt^d9A68WY2 zqMg*Lo`e5ufInuWPI)Kas;4r zyne7i11*Z+LHWT4zAj^`iEM@WOEmvzE~tWY49FG+Yx_A%QFPYqWjt|91Rlf*F=6&7 zQNUT!uR#ukddhN0^bupc_?6+B{dr@eKgKBmV~QHlwumU0$kBrNXf9rF6ZH`$fR&aE zP?sn(Et0OJ>ZS;jhgbZWFbD&H@Zr$_+v^29&Xp*Zo&4!6d} zwPm>8N;*$TV@LuXb|VxteCm01KGp0S`I`vrC2~cjdUu|+20`ANl?&0G&ON@U~*2{;qy29w}=?IR~jAS7MS%Ukj9NI zFn)S~O_VjO4I*$DwYHy{0lug}ezO%LXwwFl51*0f1uKJBkEw}H6Z!lYmREV9;yo3s z5tLv0JFBU1U%`kwc;31%vEjHI^SM26EzgH7HO-$!1-AD0a?DBla|ND-j1iS!nXtHZ z$pZN16e?cyR%~Y%Nky|<7_1S*a=KuYCP&gs;pJ%U;`UsKJQ;JFmcZ~8L-TjO!8K>j zh^|uf%|3KT#ho>-3LqS>o!m|@xJ`|$?YmW%ZMZl*VGse2ZRDf-QS_2q69XV1+IyQL zQ0qOe8S3{))sfT4kRD={H6)V~y$fcjO25(y!v7EyZ8M+s@oY<4uSCLy3dR)f4F( zChOZU=~Rq-2F{vpWV$fk5ukka zg6I?$(zD#01$$V?Ro7ytnCkHZO>19*A$6%kMgcToMx__$6X=ZeKUe_yMMu+#KkK|6 zmla--2jJyT781PhNLxfaj{3_(pB6BRpbFHzu!$ZMuxMYo_Ri>x+CJ)XRmFYrrbO^> zY7-F@F^BC6hi2q~CiDzvZHmH#$;}DoZw&JKJ37vowIU`KWDpQ^X1e8X%zI(4i)X!x z9XY{MXVJebBi$@MX&Sg?3cKA|(`=9UN-JaC=B4m>L+*Qd7#*48#d8lfDR7htwUyLvARg^eU$ywL-RcuY$(IaGj-$}IP?gIN1 zK4)M(p#=RhZei%G=kAQ|Ko^4=Yfk(V-VMoi%J=s)5LM;m*2zttGt<@F%^JHmmC#;U zL77^8)0mE$|0CFvB&5f^EY<0H$HJoD652hP-3y@wZ|fasnT#mC7tgW9na;Dc*c+wZ z^r}NV9U)#1gsoV5pUqGDnvXdSSE@`xXT|gh|=~(dQ9H9tf@m`L$;EV3_dHuTK0MpTa&<=esVvv z=KZFN*-N^&jE(n1+}*<}0<8aso`~ti_ed!3->xP|S;ZY;OibR5j6WFYQ;ZRmpa(=7 zA(fe0u`gEA1WfJChTA@(W5>cszYXN?(z={px^Ed#$f2ozmxxN@kVZA1$b`e^Fh}=} zQ7b$bNgj~h`t$W2Ak7exl7iLO*N2XY`6VyUxZ{H#?WYvwpabay(%p^Drxy1o?u`!# zs!QF5lWf?`8H8zLX;Sk@Z{lLju-pSV7QJi4vcuqp?3tC z$Ekf>-o=snlujz{SLUzzXV2`?29-Q4;Oy-WGo8e2t9;<@&OD*l?T&kDL{u*2OGNZ5 zp%Ungk$;!^>18T%w(wFU-%mK-x>u0GJlVId5NRShA_*mU5vqr@BpAyoh>@qyp?Axa zaW(Rj2e!8gPSdwH+B^l9JOxCuu=ZFp7p<=p==T$(B_SSLXNkfXn78aZ1;bpLs-hAc z?YJRX3fm;6^2vE^h{!1f%j9Z0L&hNbPB2O;bL_)60N{XscHo4ERgO{6D`WD zHb>W1Z^4%IQs})?cc<9-UGw|LTU=3$z;5x8yM#Iv-`$^f&+2QGs)45X@g`A6dq_O{ zRL%fo-EmTOa1${*g~Fx+J96J%c=$bXZ~q=gxRlw6C3gAYYD0OPu~U^gIH)Ex}lz7-cb}^N4%0UZHn1lARQ5q=CK)&jK00B3OzfuNetkvq&8)K zjFTpzmJ9S^-J^i+5{_BgnR`QzKOq7q&cIHNszdmqK4HKG28QG*2l~B`T(Z)<1rWWo zPkdYBL#Z2Lq*BF7zKi-mDe_(!`WtFzgxT_ORJOAue2VcUJxpZN-|yB%L%g2W^_AiK zE+^>0v->OsmRD6v^#SB^xXi{89DDSG*ujhWU}x4nXu|;iAhgZRmm>q82v!qFLv4GR z@C6%LyqaIjpxl?xJ(tf)Us7v1DD67>&Yf!wV3RZchOg?727hYQ-9D^Omr19gR=TgO zeGT#eL8pLG7=er;Jgr1^Cd=bAViTM*JXI8Jyu0&_AuV}O6${!3<4fMO^QXrg78z~T zYb6Z#LqUV<2J4F+8KGY;1sS-syf5vI-(X#`kJ)@A6oR)sXfVjCtsodFNrE<*9o~eI zI#}T~ce7$yCYLtkK~46Pd$V5;RyUXSZtR!c(UWOpLz{!oY8R{se1%WI6PXz^A;Vym zE=N7`quLzCBtDpuin-98V|AHJANUUM2-vC%jOPoiWLo*Y4e$r|iM?5|cMi+hqb1BU z&E2(G9)BaQw5lj&zlVC=y~0Fek4$WUpVaDUEIF-@k?mJ%jYd`q4Y?Eug+#DE*C*aa z1a&Q58EpAd$!14(LOzv#8!bU5TPgoQ18EZ5cm)o4p8zC8(PyuVr6-#}+l7JHkt3aa zLjkHMp8CZs&tTp*GdN#iu6&^rM-pcm8Pkf z0w_&nSU=%xqZg!9@~5@5%;C7F>LV*&cS9UvE^gMK>zStkME9hgT4BA zuk!Zc3N%#CVv68d@R{&?3`|LrbEWuB z9G0D4wcb}iJEdGN$HxTWP-(2IH@;1H*X{aymOTahP@~>K8-R`-u|^JW-v0SL*N@N1 z1_-gD04iaoN=N9vYK6-D+I|+6k^8s@u;ZF(K>qf(Wj+xMlp*2oS&sj0fq>-4J++&@ zx**ixchzy1Wxxma(`MMf5`G^oeu@rLXTTSlsUa*&11Z-^>PH;0EAV5mx}+!l8htl_ z_GKqgU?9j|3pL+z9-KT{@>gTe8TxXC4l?%5Z!Dr{N9ZCXk9QB1ooqEtyj15V1yJ|) z!Qsme>fjzL`Ah@3G%51}KaG4U)qJ7)=2vbgiAqcM?@<7o{r})mD#bv< zal|p&lS;{jh3WyKqP@v~Rf|Fqv9?B20;v}7WOA|FI2}|8R2Z5Up`41;aop{f-v-J! z*!<3eWa?~X1H{SdpNkd2h<=(?IuQi(KjeMj?QP!dg_{flE8>Kg`Eg!u^bnsG#~z&= zo?G8YA=QMM6+1*L}-231??9$cfP#!m|mqRL;67dtRsPnnB zEU_F7#Addzw{vxo+MQrsP66~L9y@B~RvB?5FB*iWO;6`SY)9F%H@ouQ^=(EnXmRL( z!mOp;SPYuL`a~4GkJ4o&s3AJ2BBsNhFp-KVI{}|bZ-D?D} z7#t6&X!3);I|!mKBgCd6O^gxB^?zwc0V`to%nRiWJmzl&(C>cLi`;urWung!9}`c; z$mc2^Wj{TrcSaK_i2$~!#`pi%qkKcs>g^u}Q@M}0fT(*5^{E5UQ~Otvq)gjCQ#t(b ztWp5Y{~(l3iv?bu)2KntHM`weRy9K5|Mh>T{%us{#_V6kb~eB7JjL;+34c&*#qP)| zHk%MahP_R8YCzWOh4J&hx1f#*p$v^r^tyGw5vPDFt;byU{%xdzUYOr!N6!cB!p+%X zF!_C%8#6B-6#ZJt_I8TZNCpdvAwmaKU(gZl%NBuft~>m`Au&9#4zbjHc`jWFSmVbq zdDt$nP9v~RJRt``2>f*#SgtddNT~TKd(e)}Zd*?D(`J`%LZK{Xu#C-SmBY*rSH>U4 zlR5mj&>cPeU%Te{^=Kfr^Rc^QgMeSR{nxLrB_!&NA08tKc~EzTqC$ZDVe4w2wZ+Sg z5VK`SO9Gx`pbKLQZlUYuN7^#`!(4PRk+jmk=+ZbbVkI+TRbkK#72tcfePj0~!@*zU ziHF(JMvz@p;0r>;&bj08{zdiP>nXl7_fiOL4GZ1nYeugztbNowAn<>mG9wfV0({=X zgyYit`A(S4Z%&&X3k~f~hC{dAmQR0|@OFp&0rrbBgUWCf*2qe&Pe|B^3O_|0(6PKOILSge6kT7OJ$+< zmQn!q=leV!!7wCSec#K~~vN^i?c{6E}pewJ{_0WyewZKplEX(cQS-g>K795(mgP3ETPh(a% zYboNCJs&E>e;9G4Sp7RoYRKLwdVp_LY|L>fix*d{aP^57tIOG3zqe${U}ze#{(O7a z3Y%FMd4DoTQf#p$LlBt!fy+z=v2X^X#sF`L`ol*<5eTg1bG?1%-d;KmJq!R)fpGr{ zke77!@Ce6}1PBvE-mB|pTkNslxJjKoMCZ#j*j=8rkxBUo5KxKUbw!x|%p)n)DC*#Q z|8N%@BnupNb-|@jz#H36LyzYr{5wXL#lOT#q7yxQ)>9<^L5IL+@utmEv3^d@kd2nBYM@!u8do1^^Cf9wfH_Ku&0Og5C0FrR;S*6dn z-ELfU9!kIfl(?-PD|*@-e4+N24wef9R+=8zQ)b3A?AQQFy{#v$25V&);P9`HA9Swv zNC0f7U8|OcW@Jwd%l0!J`M-#^u1OA2{oKx~SBrFQ)wiT_-)fJaRA#jj`|bW@8Y5*p zohZ%^6><;^Y_>nl(VDoDWz^T&|6;|#z2zZ!uZ=$xewnnx2-kuEam2uQKzY^_D zq^#x(L7X<=O_v6Acs(EBF=>>dN3n(r%%gTJxdI=nIX?3HQGsB)Bxj(7O@5ts$$aIk zUG~rq25Oc)ADC9Z5TFBT2|RNR^5gq+;H(x}iuH5cY$Y_Tw~YA+Nn_L)Xz#hxu6OK| zX>9deJ0`J1@3kaqPm@r zPQ^Rk(9H!zUx^=vPM+@RrE#;ylj!mZKUrM&HFr>zRr&m4_4mRUuotB3Y~a+H6jYU z_90pH!Zat4oRlzSC4n==fXRFDZvoKFXKRvQV5{gf8`uKI(#H3WkH7g5AQhRHmGfbz z6us9idD#%}Hk(Ur-C=U-{Sr1^YT}R0s>vipO0bYLecSm9VeVVKRjtL5hkl!zO11?F zPa&Ek(o4!XpV73BUHSi_Fz`;~RuLOER{TSPRcUoYOr3n!As(Qa2Z`NZuB4Y9) zKcr&HjjE=(($UCcq*lLdxft^L?J)gabPC!QM;KqM&AH=rxm35`>_X{Ir4KJFcwBw3 z_x4c$EyK@+{|l^~-+3PdT`sXVfN6O|%k{f|8@o{^3pL|xBZ&o?#1p3uLRIV3Pl%#N zfyr)8Z#!wiwv7ky1JNM>q4AvCmy@i>;htgM4tlez$0-MpS9DI0va2fR0>X%`qS-Ag zEAR_$6}%5~QA&7mk&zyM&yCowfv%F-coVVpW-$&Xje_;!9!GJ0DwBp#glQeN==e%Z zeXiPm!9T7wyF;`^4xjN6pd+}oG(-83rv(A>(%|~S@zCH3XXgyO#c#DtjnC~_(N_jL&Gbtr%&SpVp3V7}rHT#WkGz_(zs!c`uppoj>Q>Tsd#hX&4n9|SP;uM{7zZh=x> z*wokrFzF2jauW*`yKN<$p0Bq$bg)!sg6y+Jqbmx0Z%xkMyq`Zkq=FYEe{c@Ben_Ws zr{imGr@wqSxWH<#pWQeJvQaJhmjlMV8Xf`D29)KJIW50q{(GC=jK&hY^0Q2b^XuzS ztCD#3qk&+(2NoS9U>>AblkK}HZbhPxh))py6!6nx?Sdr`r9g4O=ce!4e?ho&`Fo9T zztn5-!5r>tXNNxt7bhNHL^XZ{MijG=dF<6{kC))UWh2tTX#8AZ!*cN1A=0?lQ zGHM6D@CsmeX6rRZN>bNO$;lxY*x0am>Du?VC+!(3+S(sUKt7?+4_C|UVU%{^s&#Wj zy#KsI&Iw3`_%*|AfuHza*4l4jFJQM8F-lPlxIc%=UH91;oh=cbt8Z48mjmo%j_SXQ z*a3?WC=J=N|1XP7jO@>t4YPm#>E%)zdD*%@o+TY>IF>{yfIFEL$Lq55F}rA?X*~@Y za9ADZe@4x@nfouOD9jsQ+TaK1+D`1L$*+7y*7@i7R=|NC)+Jx#@T7FS+=zn1pf%h9 zpnZY6Xe_<}RDeJ;xe}4X@I!;fzugM?w_ACKw+bNU{`Aoji+h_gt`sn{%{aTc#U(u? z*Fg$&ST`dGk^CrN%e&yX1lvY#)S-=`0O&i82l;l}|@o=0!Zfe&Rqt~&e_>WhiG;0w)JiopO93;fV z#JJNixmGKHEa24#*V!M`Yd;gIa{`wu`VGsylwy(ectGGYQm{1;Q|}zgY2&-@{MZNp z_nyHofB0EKAP%g_@Sim)n-k;~rwN{(}% zoL@qQg|EA(J=sxTJ>IW!JH=kNp9py5i|!U<2p7bf70IU!>_zRWlo|(r9Q8gp$0+zL zbCNh(qF&fwlrUOy>u&AD0n~FKQozp9r_59t1eEF&5RAR(YyOO6A!i1T*BHM)_;EL7 znwMpNl;yr=e)x}1ysb!6L$Gz3T$}VYDIq*n24Z8_^e#uY4yjBk`kx*O6M6xjs3iKr zY~V{6^|+>S^Cro&|8MBeZ`W!KqTWw{EIePK$IzY{gX&5(5FelT8=CRi0RJoivNFBq zvw@0b*FlBH+tVn3Mryk6D6DXI8NMLKY(oyXK23jq29qRPM<+d?q<&9gSl^LE>*>g3 z*oI6mD99FgYF{XyrRhbU&U%B>UGU4PhpZ3`F%%R4nuo){gci{arN@jckb7O^H~CyJ z1q8T$W^h`RpF94-eY%fIsdapjGXI$&n%#)%M|vN!uOrlvboVou}7vutB?r|k?e8? zpT;{H2<$GNu1mZCQn_Yd@ANScG9CdMz4butJHR@Y@^O7kF3aGU`Mv_+^53(~Kuna6 zx+?&Ak(WAhb~quXHr0P|DA=)|8*@zkd1H0=f=!Zqw4sPCy?bDEU$pT z?p;AdB5k0F=s-9sN#xd+aSOG}@QgS@A}};oy<8Wj3v~5wye+5W0yMxH6$kJX6eIhy zC2tb;p0kp|Q;tGx9@jEJjR#IVJPv(Va@~VR3N#!Ki4+1Z64fbzc@l?pGRahk09!f& z&^$36Yryw#rImjdd-!a+YS{eJZGC}>OeBbWv{(V_Euja9 zQ9gM(ZUOE1Qk8a+KVH7uCHk$?T`9Eup2tBdl;L41o=Vj=tr)h22s97^l~kB0;4%xc zpdHbM?d>I{{ujG_-A48^)5h7{?&&b>4W%U-w;twf>8NEhxmBWo7!jUFKUEU%7vS|o z;OOYM6u3o}$>|h!=VXXz+6=U@vV~od1Uycq(ocoXk1t>V0chz&p0*Zgs+19{34(cc zzXRity?Vu`_;Y8^h{fwNQ;Ig%9M#eN4mi-cPRqw1noN>2m_-*`r;6rd87f}7YDMFb zaIX7g?tj(qH>YsU|IE9JIv?(0x!tBVU0VIT#w9VjtWecyGNmpC zq*yACv@-m3EqyZWfSBmYQ12W3FD9C1rAz?|YdhoVQy;lMBeNK`F~sH-I?fSvm#f=PX?l8rfmUv} zROGbTxI`fH`!f{`oO~l0TnK>FTr8Lz!sgVKKsND+7cUcE)b(MeMI}VWfA43G5xVV* z*cAn|QkW2gy;-QT5hyTm#VvPt{IlrV|DI!7Rfhd%w6798Q%aFIjJUug)o8w}Kf8ZU z1Tv0J!tO72@Ux35S&4KgQ!%~cy8NGt%bj_`#m+-RL&+T1TAV+B{=y)}-YWg}D`ro6 z_$_>|e5TAg-tQMT2ZjQ}<6g=uc%yHjQa4Wv^4j8j+rVqI-25hz$m7$$GQWdNiy_9J zV)OG#r&wQ7^xo(0StE9Pxe)=N7E>op0kX(ZSr7f;$e4ON8g_F-F(nC!Z24ISM~`t? zBN^l&Bf8x719XBu&mZ05(fmE0@tnn_4T4-lJ^jBZmk(TC+@iLDiv@gG@(eQV1cF8>5n--?hPuOBrMd4Tldg#+R?>NK(9 zzSI(c0t$SMjZXWq9atofPYr1>P#WA6eissfIt-L0Lh({qki83)Xjyn}9vcM$1l+Xs zIomuQI>@>kVpLkRWoK?7(sxNTihpJH)M$qnCI|<75}QRZ*1BAPuvk4+IB;(;15D*aex$RE++eHn?%{b3Lrn5Zb-xOVU*MOgt zfYngnez^to>ltP6p+c*<>AdvsPLktV1KfmeQ@pkGF!(?$wQ3rd-{1Un6RQf%e`+6? zf~wM~Ni3Qni`VIU+jC!AaB*so_x{3d?|^-#SbK&-jQcWLb=%?2T5y1%dTdW^7pXz~ z;$P5F9~`9}yz_f|?L6Pm@4Rj9{We#wf>LYtgSNT7Rawr>ETie;=&tMrRZe<%lVViM z$x4^x&#S4F5;nVAqHX4K^&)s6vmt9DY4`EKZ4MG>a*CL@Ta5aE2V@W*C}dYJu;n5g z5oUkKeVxcM*}1Q!fWZ#yJY1N^;^^oA#DfXkj%Gd_X;x$BI~}|a2{_!S{IJq!!`x8` z1CN4nf%{KPNQa|1hH$o6?0lN9TMC6Ra&@dNhI+%0W4c2pC6e48GkWyh1643E*gE|2 zrhkeP6By9g?6hf!K9xcXj^4DI$ix8{j}pLuaUIQ0w*SEbgl+&6-dG7Aek#{cWanhh zRQn3J*)O9b>hDTlJH#PNo4W!k@OXHEkwGaX{J?#8hc_l)%y8WI?kvW&pw0C=yMgM6 zoh->4P%5CX`9(Ez8s1Syuj(Z+W-Y}nHH9@1vw)bHQpNTV%RP|k(6gsjUtX`*`)|K> z2S-bk+$dxkxE32^DK9WnbyNQz#@;fj%C=n>76e7QrCYkYLAoc>ol*)2(l7~;?k<5T z9TE~El7e)%NP~2D$G+yX-u14v_uAw8_Vddz9>#so`-(G<<2)AJ1)eK~o2;%z8&vnm z2X*F@cmE7XRY+pQIp33@s>5)zxnz{V$ofrNxxD-1WLeCH{rqaL{gc2u8mV1Z+uu5# zLE-2cjN}m)z~ffZgodeF_xB=mHEv5w z@2EJ|KQuSWvdT4h&DF?zI4{2jb(9t90I4elj5cYRwAB{(tw6!qB2#><&es9Z^PS&V zKt{SPOT;4x({;552zdiZ6k>q|L0}hYgpzIx!+{b3zLt zptdZxC4U>K0=jz-FI^+5+Ob#xwS&TEQa9y*1!Z+h+}gHP)qw0B^N^+8?!f? z>pS~Uw?Ck&%5==cmxSx^0zTz6^Ng;2GlP*BK94_zEdy?bCMn!zvsOf&G@r-^B0ZC7 zEMzl?ByDl+4H8YNeW7U8TfO#KFA{5i4u3TfF&2+_GV6-&xTMhwVp1@7g%-{e@V6@} z@FLTTChY3(jYp6`coXc$G5*gJ1}rYyP0ku>Pg|DLROU(N{mMj~=aRYG%A@KkPkJ_h zt}_@;>jBqT2j?n+3iiWgLk`RzMIJ5kOly#$#F9}8|BCx6`6E<=vXfZ==jiR$M>@ev zO{8Zp=5!rrFdz_!GfSrODX4`Ii#636fxcVHHyce%Dms6TUp}9Q<3nnpn5luU*C}nnwq6 zn8^AvsSSiY!sCtFk!qwQxV9s9)83rkT z)TP&Gpch-h#gWADGA;|@SiTbV^%XW*l)yX0cn%NDCan7o&_&UrL&wT8k-GMQsWq`~0G=c5&t8)3K8E*l&H z7rS0hdW-I5@qEGIGPjLvlK)+Tp?KbXm4Gep^A1D5-%`8d5%v!_XB zNgg*CPgRBCzkB%d=%LcIb!BGpcV_`+!=xwus*i2jy=dr64EC~( z5@)tk*1ol7W4yXE^8cQUGO4Zh>vCWW1v!oO&DYZpGh{vNj{Jy3k(S;tjgBAwgi;HrBJhkd~`aj>Ab?6)GjiDuf)-U z(Oouf(tv5$kcxcHL9)CST}sK9c{LFa8I#VD3Pvh1sP{v9cJ?XmBAq{aS$7?M4O34~6$&w$kHw(qA zB&zd4V;D)y;TtH;viS-H*1|){>i;Mhm2h}V{v-t@Bh}Zu;gk~MU=aU@ZS5~a%>~L1 z$@DPZ!m8PQ_@Jc?mfn*RQ(^ag<{{05(D-95O>~)=`wB3asKTU~zK0=rkV&fyDS=Kc z@XDnbtiW>)6V!Hv<;)=Ya$B6sy*YMAp7A=7PIJ2I3d)Td?!)E{(Duk!WMY=*O9 zUwh!U{d_xRpDA`%1ej+m_*&VyteZ*=u6CWo%WyokkY?Of+%UD?H>h3y*0{r^z0iqF z$7a6i{>)xz0|rTC(_sVE;i!JZjK?Xy*Xqth1woc|{5H5*T&@{!LDlNt*~dz*cE;bi zVC4kiq|8}kAXr?f`3W<-{U+b^jnoWfSKEU3IblRNTyn z)$`+ybTkj?n zoNhC+QsVtcJ@~T|P3TL~k+vAzz zLR0YGCxKh+E_nef!*~eEqE-m)l~!(fc5T|S0&Y8@r?~3byONE>7{!r-8i!8;azMBZ zXVadm)BlC<2p4LDnOv|a3}3-S;?f65^mHCDdN$%8D^{8B2)v;YJ)LiK4=4JqKALf)zd( ze@xv}2zd$UQ3DB(gYa=>k|qCdP;th%WYjzKydXl6`jg94mF-} zkk9dHFV>c5K`zMN|3{$*q(H#qc6~c?o>Y!U26wua(QN>5StNxn{8~DJHRcf2{QJg7$nI-*_=)xii!< znqF2=n!3QM8HLvdB1SKSbAkH4Gga-n`}TQe>iy7aC@mEOO~` z?K&N8p2e|aSM7|NuXZ4X60&zK>av@GX>6aJUcWOD!&}fho*T;Klh5>tQ8Yg$#+#`9 z6VhA6e`YGSEAlR))jj-{3TEBSdm-tStlJVV`4lpHz#R= z$KelMRT5OVGlrvDTf4+av8NV{taRO+c%hN0FD!j~43l5MrHmiO?TmcZt`w~CeH+Hb zFE75uZG2Pb5Z9{C^?EoP^m45cnf2Xe&rej zlt^++=4YM^L$@J)WLNnod3Iy@gv&n}*LP`PUNk(3C23WzRWSwd4 zUcn0>gdF-InhY`BD4^@j6{wmR4LS}Q4(@EcpyM#{R`ZxR(XKceIz|>1Y!T6WJ2BHm z4^|L01o^$bk~mYpR!PE(j&w*wK-`NPNIi5J{TM(_sR`zliqOqJO;sjGLp3(Uyw5>@ zDAMU+2xIPt%WvBOy&03D*C_M;du;7qVm`N2G*FWGDcwpFG+ffe_EjGGV!IlQM2N%o zV0HoghPlJbq9~UW#5~UHyIxStXW_hgdxl`%#g{K_`la#EgwH8K77387sjXh?oTM@y z@=xb)n63cHr!?%U!FirUC2K#}s$X|y>Wn3RU1rNt&Z<+vSR}`#$ymhVfJac_lY$emNV*89GBmJikjfCML?eWBd)sxY@?jGG@MvA!~ z;j6ugf1oB^7F`;M&laJd)cm7k7D%B5tqLd^d< zj+vnaRQFl+>x}5Mr>opFgQDQY*o|Qrm?M)$2=-o9&1VnnJ;dgm9S*AEwFh{E{afVI zEeVv9jRC0-w+~smJOX^*5+MnuJ2`2LNn<0+v`2?+zL*8Chp6(de1v)!3N+?xJR|^a z9eZ#zxkOE129&UXg4-_zfgJ(+xhUapZ%KxkU%V8hhv7x^B0WOI9wsrz|qLkV-qH1`jYB(YhlC|kNn>FOW^|Yz*)Srgjv_0rE z*=R@vVcmRQUwQDqeovnk1l|n+FtPv94FT>!b7TNL=~r|MCp*aea>5mW2Y@ zt)A5EWXbIMG-LKkNsKX|-cOR1qXR!sB`^NtNz@T);0yCUPQ|*VLk&V;DF!@O6A5)> z(mG)8w)CBkOYrUvb_ASmFYtgwp-ZiGp4+iv;x{)&ddvcRw#3A5$7A0Nmuueh2)k|u z>>D@s%zUSHmD>_aWit$MbRf;M><@|Iv9RwA zqH^)kuTadoT9HsYiT}OZEHcnU?v|?}POg2joh1P823ztR+u5Rmv2AU0$Y@nwzew`c zlKaei7*r=Ra?%8o5};U7WMcEaheU(I7f&-S^Q1%Fq34>2#mhEgx{nrHEq+;Wyzb9@ zDaBHeYXxsJ>-(HDiGT;6z5y41ZJY1bZ)G?v9eQ_+EFW_h18O)H-6_#d9*})?u>NnO z|F!#|V&1igy~m_}*9|2ooNS&blfyDxr~!C9-x6Id@;@*_K&D{g2zAP&PSE zSu||fb!&CG5iGH^N_HQr{2Hmf<+1rKBomQka3D8UOTEZAjri?FxeO zF|rMIqlAf^)wz8zo}ktL(Y@C>tA!ar7F10-?jwdYgNaWaWB+_jg4mbBvBIny=hF_; zdbbPe1%DKcXrnqpx>r&Hs{<*|2>OyF6B{P&*)U@(IRVy&;7MjEPb7F>4Ypzhz#b86 zODX;Ex;`}(yqqjyPV^r};Y9pDdg=ca!eJ;86B34iL0c<_ zqn3v!vyrhdaoGtLQ2mBy3`(t9lAu;fHgi%U;l=c?1A=_f0iIX~M`P@{{lt}l1HGVx zIf5YF$-Xuj0>aPK&bdL;RsC2CV17@nf_Y+%OOnGyF;&{XwuP#mK`sDC{V5!Hl=C!Y zMFJe8J{ydP#Np+6ht zEg=YCGd0DP)ia^@&MT0z*{{!ZEAPm;(6F#Pn*8=+0h}ji_dyBd=SYaJq`5%li}0E8 zUyI|g7DoNr0BA~^7#CvHBU&?Q@FQlhp%gPz;AgGzpu%Z4Ul~jRyQlq(RNQ^s6ium|uCq>^w*Xm1S*? zdsoLbNLS9mVtn=kKeyCWK8Bte?$fiWEOC&Y`X~K!9RQqj+0Ge2KUqWKM9jbgli?36 zh;TNmx&#kA2C?eD;mV>^v_DZ8gTPr24p=v*qy2ec)T^FeZc6~_f!`bTx6rkg94;Ot zm!DG86LvU&C6h!0M|>hMg-lt_Z=cY(6#Uwv*iy)G!{36Q{3inN z+NAOqP;aSroLa}10|Ba*{T|R{et1|%F!SLoZ^i>n@9g0GXt!&qNiNN>b)j9iT-rQ zLr5^WlM6VcW=Lfp!P|G1`kK4QKoOU#oBfS4d?oDkAv#pBN|WZmFJD-I;4XT97l;S4 zoZrGvHVODWwR~Q!?H`Z;k^77(? zI?~H;Zzk32oy>XPPVI)iq=#fjQA>v`wFjeZF1CWMya@faR=EKIC_BmxWeU-L2g%xF zS!X=BsrYXgP01*D;!e@9<<;0uAwc_YV&`nIJZ$gkKO0W}1Kf%*fb3j<)c4M|h0+p4DFv zv98*`3wFeSbo!gp;7flBbKoRep+$S$6opu%b@ll zG#1wOFi1L%ezv%%B!1GH{m+i#Tg_&PX1!2Kl5F-q8!1qJ4y4vFc79jN4`%RHIscU# z$P#(Zpq6=Q{`u=yPEevlU07JKU1<7odH3-tmecK}bM4#T?C*Wgp0U{ zKOwj0P`RgU<8I}+Z|vsMMu~VoS3)(m&sK4-5!iEH>TJyxW|0Vd+KuPAm4 zqs1BUk0dPff8CQ&I@l_Pm@DIPXAuBVQ3(p_**CwNt-}C4hUeT4f2xteY3Tx4(@QrR zRB+Ktp-W`Ss{*m{Q5ZL>XYHRq#x9$XuZ$g@ipKxanceV~r8?U1Oake{O zBQ_HMg7fkcB8YJl3HGW`!Av7mJn{!EZw;q|Y9V8@8s_ zc!%tVJ@JJ!B?=r*mYl`}xg;TAk$g#V2w ze4V;8<$0sw1fm-3{|8qArl-CC|1;1a5X&^t6h}_q1~d^Xr}bBGBkl$N_E@1*4{O*YK@6(^-1@vbn*$7w+4*!9xr}D8Hvr z!XFX}=wSb5JY_z84K^$o9$a9Lh(^6e0*;%QxrU$|cO!8an$c;T0$fuMBCSU|*m`Ce z@GjKkl_i=Z5nb`eU%?3l-_F#d1*aQ*QXP6}T3D7Px5H`GMUI&0>r*K1gDZfx7a~U%#??ix80dCf)=;jm@U{@D|zxU5ia(nuAjYxouQJ@%-Md z)}Zf)gAF4>AO%stwtq(1}=34+S0t78LxfpW6;gp2F2jn)B!k650SxKTRzFkbi`MKkt& z=y(mjs=7R3S%LY=sL}5+D4YD+`F$U6?P_+wPUqytCkSGS<*#uUC;uXa`iQOhQ2dh! zggrq#kU(0#(A;pkS&)XJpvK54pJ)%8-WzH$gMQmp-)M3C2phut*MmVYWdhmUAjeVL zUhT<<07=62%m2gz@a?Jl51qbT{Zkk|Y34*XTT6T;dVfPnB>tvM-D09&_N^|PK*QP4 zD$m^h)~-$H!mld(a~bg+yKe;nBGzDkEKvr|jidQKdC;N*wMaZk|9(Bh$BU5*xD0A^ zmX#CQMA&i~p*h-rXEyhGaim^9(Hq?_a|pdor2dq&NO30bL^fNC3c%nS|0hd^U#C2N z*f;dyk#C!X&k^cki*KqZgoyyw>>15lBATz2Y{a0$YLl;+EagdB`kbqA4 zy#8sS72nd*@{3mA!qwq-l-L)p_Bc{5#Pe{;B5_*ht!whtfit`(Si7;eSI2hma{&;n zb7IS+-tFWG>iSU3i-o^@LRj(yGbXzuarb0x{Gg`k|L_+nB$|xYspwD%w3x$3+CW7) zW5K=1Az<>8$73~iM)l8+{7Uo?^lPj?fTs2K@9>ck^|?k5N>I4zTfU-=I}n40uCc9Q* z)}((f?2ce_pF4hnm-k0)`*=A%P8F}A$-6%3oAuyZA|nN8F*zXSzUH%nzi&5to&}(! z%!hX@*PeBR8+rBc?CUR$dX=9~)59h4$;Qyj@RiP8#4s>bK{htKIj)C~J;vVD@wrR& zh2nG`ImuYM*lZzSZK+UV^1W+pg^~vtur*K*{6YTP9rF?lt+NzXovfYx{_sdHhT?J2 zLC&G!#>XUzQMBlSjPS2iz`>Z|ATkV_$W)pq#xs~Alo{1^6xy+3&;}LxrY2~8Z?tO1YO00arW=~KQcDMiw^}&_~yX8v_;hny-XDYc$!6=pE-*@Dq`T(D!C|qXHcfkA^Gpu)=H4VfxamFkSGyu+ocjxnvF;8A z=2N>ro(w`Cva_6&<9;q3OsI$(dQe7@dce%?MQ{Ej(7ZtT{ZQF_s9ATa*KAhWmr73< z3k*ovhew@)r^YoH+1c5LyAz`%($i&-#TUxUJ3DB@Iv8an-J{lcwRs=*{$OI1^qM$m z0y}rxi3TSzD<;x)y?uD}F;-?>g?M>aMWDl<6;!&d-qcAc*b@0kc%xLv1+Knz#<&Df zJHHC`XGcbvP8P!?Y-%5@;8z|E=j%plOLNN-o7NBJPqQ`TAh)xBuVxPZ(ocMdqO zzHrsr93I3_Anjfi05m=Y>8sr5K6TRcFv0`~(-t4F0+IaWqA&e-Qb{IDEvDl>fZ)P2 zB9H3{;I#yFY7--f$o$MUy#{Sg%dcR!LFz{Z1GVt>+u#=4samd5?Gp3|yS2ZKNCNK` z+Rq0`{Sh$SA72}BqMKX>$8show7+|^)vhZ+(ip_#d9=T^DDt!T7m}%X+ zkOoBajxZoJ)_$p|xy191|9EZCQXQ2Zwoa+`b^@UNF|>X_9dTnZ zL39PW4u~b00_U=EM)-l3{Z=mF6TgtXHxe%j(+NLe3Wm0TN)7OZfBzOi;twnSX~GfP zoeGVXZn*sF8nj&~#ke)S{Rp}qvIFnV=e#z@-%*LT_|vi*%d#=ti-rTp`tq7YEEj-K zi$YIPSW?*Ub4-AY@1e^d?oBY7@6|2^fa8Oqi8(;?WYi=SaLP%!9e<)s6CkdeTwC>N zcYskTvI9cK4Yjtv3;9CONdl1Mq&7;BseI1ZOOQ>4);MiK8>$#(T?`B0z3Vvp^gV85P!%b=(zLQ-^wG(L+?UmpyPFGzOwocK z^sz#>ew4-{WD%b_d%c#4-%B-z-Qg0iYSet2{7+DUWK#!76ygD(g(!Y_-p>bVwAtgv zyA~z_65o(0Qcgto;D8^g;^kJS2y;cc5OuR8!|(6%j5_=DR(3uD&{YWunvZYW7m`yV zRGT48w|NTCJV^dB*#Y2CoiS#I-DWCjg2;eXx&pwQ%PT9m($A6{tbr}jJXU0e^B_Pr z^>jn8DvsU30NxqMxBjLiZl}RETPtn0_rNHDG_OofAacjd+48TaMh#G85HAthMQjWlOMx*lGM+8wv~uR%6~-%h%|Ml4 zb0S9!K$+=(_)FK%?4X%A@Y98guJ3X(U)`Py39bmvB!AI;1+czGEly81IE*?#O5N#` z7Pbkz9U#l{S$hr3g768j3u5Abg|2|ul}f}>y_Et=7$Oo5Z_JlxESqRcAI#R;jhg}W znuKcs`9QdN1+Kf}if-)3hzHX-xgZgaV=tc{G>SwB-AXBy`%Rt!Jj1CCgy zQ_VmUkA!l0ZlW}KouPXjKbO0DFOla`ggO1y84myu!``M2f2^B#TXg{vQSCQB-dt(G zF`M!+6nI!q*%o9}HU`s!fhs$d@47t^p9PT;J_kGDHekB6cN|%A`RqeIhtnf{{Td|~ zwzRgmb8TYx18dbjapA3I6+F5M0V%Ceit7GHoDp{Tb&?Th(Y;1~d~-qY`mnuIxfm!g zd%pVqZuUvlUj~`>pl4hF)vS)X24HE_iV1X}q(EsK>H04oLI@^hcyLQ(r*{hA%(!ly zvv{BF#w>{W%T|it0cf+VN;)qB7NxkpV-rh>;*&Qqy6Q=715r>wfe$VeS}?g}(q*qbSY=u$BA@w2 za4=yZ8)<6#xm9h=a^DFs#&jE+bBq7^AuVVbqV{1tOYc83GQ>J+>fJ z>HNhHdhkX~uFn`^C_miSH3H1zVa8f?_r*aNSMNw)1 z&&|ayZu{s=J)nM&iMdKboossID7MB6ew~pDz=7ao;`I>w3*|kSyI(FLFgD7+E8O2? z)ch)5)%3T9%XtFma)(c1&vK^M32oil&cwSQd&_464OIb?I{B4-cyWCxo@mKkN2!XCy%wcfdH2xtFx^)NUz z%D;#>?bNA}X5_^XkPNU3S#t5`X=)h3~Gc z6{au~xyA1qH$^vOg%Qm&g@XW2nZ5CQ;qG4qXG2!C7UdMn?jd6UF>M_E_0xa>RvT?n zcgxZ43)zt0U${2JR=rN3iM3Ab!svV~xuFpiKYZoV6c5-XaIQ@-8Uen$GS<_1X4OPt z3?S9StN|rtjWhK`-_+368s6vuvrhpIS7Z0yqa~H#kxh9UD3qIGvYWp)xkH@^%m@ddyOr#laHD$oZ%z4=?9N#e}e3f5Q0Z`Yt6hl>c@~F~9krFSIQVDEQ z8PV~)UOeY84q5v7s7lOgbAZ7ChYk!EHo_GKd1vurakwDu8OX?4jq9YyiVO45C*Mxu zyiTY?-yE;yIwtGLB z@y&K|RMTiW|Kxa8e=;7TdAHG<1rW;U=Vo8n2mY9=^fCy&=66_#X!aB7uo48cF>DDx zQ56`sejKDhL7q~~6+I}XGrnBIg3R(@ws>`1?*TBt-YXo#a}JHV`G0l6Gmx@0-rZjx z5XMyGPW3Vjer#D`P)!f{rD>JpFFCF2f?Po!S$4nogX6)V zib)wM2wQzw02`kYCa)_h_ZF5nXmvDR*7w~z;JDr%Esqq`Qx&*+GgaWIeA;a^0Hw7L9ee>>1j zJkmA3BP%tEG%ul--aVY{q}q-OAtoy_30CD!WrbSCJLFgK;+$E74MT{^@ zYc`nLa=+`k>T=w16rnm}VtN>XP`o6m^e4wrNf@v|4>dY6v>V_)we!S|d1#}!3Xf)P zrYou5e^{-aSg{-Q`t8QCC;{OWUVbJ<_(t`4LfL=u{;|b#xnBIR^Xov}$h{t>P!0Fu z#PpatHoZ-jvG*hmQ7jvC=x0_St|b6t0Gh4Uoj6IBQi^{xG4724Iw2Ep^xC<2fO$R_XbAf5*Yh_#-kL*I1kfb94`9vADGy5D@bx;3tl zH(73s27)lIYdX-W@Q?o-aE>pW3(_A@O%6@wU?O;RMXtsdC9G6{ftW1)uT` zX~2u{B=U|g&UQA(_H;%4?-3nlYjKZu*N4vt|GZ?pLBx?`PNL@#yrhL^34qH(v==Ly znbeeu(v?82Q)YzW?=;KXwcBY zXwpblIoGSf>0zdq0|76kod8o>t6W2$&NoMf>(q~e#}Sd=eg^4cbss*{25h3;=|86Wep1SK^*to?agEu{&$UsRN#VJwMy6>Z+zUh!w~Ln!gf()M2pn2 zQ6gsl)JZeIW3Jb`J&CQH@7D(~`($^;Y$!GfH^BgV^Scn$&yVUFPF(=G_h%^9%fPg; zR*WWWYpfOBM0R zwQM*SAn%6X?(d0sp&}|CiGsy6ZoG)9RU3=Eo%?~7ChnGSIpR3lz=pXy&z4}J?&O7f zD+U7h)BQh>!|_OCqwQ7r;d$oo3=8&je31#O`iSe6o#_^~g!-cPI}w36Ax(N5J@FEG z=J-DcgR=rXx?hXGLaqb0<~;%~1)23YTial|6{lz#fPb4U){yt=*L51dCB3cu1>iq( z0(coFxp-js-);+l(I?`1gDw@gV7?Ef{3sDiDp2uC5*SucWTX^@22Je=lOWAyOS6sA ze4_UCW;NYr5pAtnp~ogB>_L+(08C(-$2eAy&p+!bv&C>sUnf0?y^Wcp@7(}o$>?)= zG#4OVFX;y7t7*LR16e#b>rtK0z;h|bUKBx8L=BVc!mpo`egb|vjd(_Cxn6k5c#}*W z-<@0h^~i%n^9WNafBYbGGD|qML7m;x??{d-A3yallo!=jbk>5LM7+?m_(vAL2=w+c zyzRocG>Hk26n>mMUjm^Al2^XeYJ5UH9NxM#yx98is8WBy6Z#N?A_rL*Hu6GUx=IWs zl5pl$dpLWp!)}VGw4rpT5t9GmV<_?M573iOgy6|BT-Cv0P!0D?)3;KKFFx~Rg8)35 zcb9{pKeC)ix|2c_R$H!SdYhEN;?PCOam8ylhyCsC6#f$xG#&!-SA45iy8>o$JzL@+ zQ_s6|F#7%kKD>qvk(uwURyS*<-3l5oy&0(nDba8T3ttYp!E_M`S0)~}vmQ&ul8@o` z+f%aSR}*)z7|Jy^b)8QIC}`QAEn@K7 zTTp$i%zf&j$vE?m#{m7HLiVz;7&g*q$FmuhEBl4AXTol_SW0*6DIMgEb?@3Z2w1|l z#*kTsQ{SKOdI4DKBaR0zRzEenb&Y&Q%4Hw|ah!ZPQ=|b{2RP&bLq$Y89Ciu$o;Uk! zV@1lL0PGssDdKzWs@M1iIT5n<8$uC}GeU-_VS3#~FK5Hk52h{H*J$RrICGe^$i%k? zBVA3DM+zU8+(?kiE5!*4v6~8h1c^&{oodE+`2QaT`rt3&L2wX|UF;Xrk=2%A74 z$s!a1;T?L*0U)%p^=xE)`YoemcOAfFRF*&OZdz^sqi4Rwa)+Ml2FMSiRfDOId>9Oq3q=5|;3iK*l9Sb-8MqV>UQ;<`K<_ZquNt(iD*Kp~}kZz5gjYZVgF7T;~~ zYgOtH;4wf5o`?6GD4J@T0I}JTwq^?i4vnTH!AeC#^{#6cgM5^}2MyWUA`UJZnCns4 zbfP*ii4n@D5S;$W+gr)H$Ym-44XE7+*c;L7BY@0yf_2F_Oo`yRF91tR(xN+ zH#1VZn`4ccyL?`Kynt}d3uYkL9&QAq5^|yfD0BMz#vSa1s(uJrAD`Cl-GEKxy6R|^ zuL#!}i*9AEb=LI?TBOpQx0|HlYL#U-p{a%I$^PV*-|h8V%27SEUR)2l6@j+W-zT<| znN1g(0-+h(u}#RX#7v-OQN<>itx0qJOD?K?wPd{0iq3L51$3b8uB`Nl5Y}+wj>iOE z5E$>LGHXb`{G<@)-ns?o4=uepn_ z!bAj{)DT^g6I%u8Be!j*&Mu+-=-b1Ytm%1^D(uH+K2w+E?3+TN7`usOUfCB{`wTTU zQ@7SbyARoV$|p$qEvJ+EQWi%GcQ==(TX=mbOeg(w1^a)%Wb~D(y;(3E#((Y)%<@G`s_B6jVQYyrT1Ae9b!KBD)xU9skG@D7(Ff) z#BiE`o(yaFeIs*MmoPuy%7*5AI>ey!1{?3=N@v7<`}J}17Yn}OG!C+YRe3T~XkmWl zs%ZZTkI=*=F};~6QUciOS{>3Iw1tuDml4ffqL|6w7WKNV%L&Dtwg-fmj4^w^&rgOA zKT9-rJ{&QZAw%f~&I6lMfGBU*;Z>CsvNNgA$rLBiNnIn|7&G^1dV+Yf54CAa6B84? z{&4lB3L(E=*fSyw1WUgy_*-nBm^OtFod~`@DuH(Nv5R9p9H4ZmrlG_1O^UT^o$(+Jyi)|*B7)!XiBA-*DPgLMO;4Gp(I*=eowYoBTB2R+QRps5Y)v_ch?5tBcDzO_GUeT{(35{iu%Q!apL$= zL+;yYGRf8$HV)g+2v<%vhBqhkL<%8p!6hXneeX-klv6n(doXE+>;;tL#*Kp?)J?9E z_z~W-)5p!A+}@4>OE0uP_ajn1mLk$pWc4(Q%yszas2d={JNKW-dgiodwK^g2h&Fw7 z`AvbN=3)}p>V&%Z1tL-P7nh_C10<!L3R!zwVMi)}x{v8Xhkyzp|cJeN)h)at;HBN<~|ti4&zOy8DSYSQ|N1EROe7PdgR@6*KT3nn%>+Tq`C9G~U)2WWQ3(lPp{ z4WbNuYJG&@=h6`*Vz)8*Z!Ey;G&Z?ujOTc4ozMcJDhi&$<^6e|uiFBWGKN$i6ml9D zTD;kF>Ea~w!&6pzm@SAYV=gJ>M1+6&Hhc6_q-h}Y z?C1;&ds&!ZCGmcJZz~22{-m>g47-}>iCdOR4`{=_yefcD`!lFz)0kwc#pHD=e|Kw) zIXp>6j?kX>kK=oSMMh=ugJq?`V|yAw-0vO?7z#cw0K(nzb@_xNw8Et(M-$zhk9Z!{UFZ#tC2~o1nj5$w7cd!_Qf;ancWcl_QZ~-oe>8j zW^pLPS2lm;0$ZzEmN2ZHUbLxeuV^~cMK7dU$_beT?K#!jP7(^atanUv<$ZnkAaQt@ z5nlWp61?6{gr~3Qw@5)C7`ZyOUKXjN>D9={AOuLHF=GYNrT9WMXN260V|#X z;+QGsVKPyI4RhNT2uSUYs#nxMQZ_qE5Bd{d!;L^o_gMvcjf}L?`>}Bac^(8nt9$~_ z&5@Yc!0f4PlNzVJK4fZcpm-fXJU$mERKrwZ+zMnN-iG@Z5zyj3P1=-hR?i7+Kcfg9 z*MdUF7j1Rv1sNa3|E>t<432otw@3DBB0sr5mAO2$PbrlPO)7;wMx=kC=s^<4A}xp; z+$NH;@Nft!scIx=t%ce_xrhMmt0p}zoQPy3)3{bx7`DQ)z?QM{-(#T5%{gqz4vkB^ zyuG~Vcq8or1-?;j4+gVIyii9`;Yb~32e*EETBrU|>>2I)NuySt>Q z^;R@o0y#nspB+mk7>G@oQkQ9AVZrGf$fK0{g-%C?$*;^}tw!xG1Vz6Ag?#2a-r88I z@kvVg(VcSCw6(epd$<|L!Jn02$?!T{6>h6&JlH8>`nIsX{i_ZLt2oBnKEZryT+e5j*^F*T=1-9RCQqFho^3N~ zm926JHW(O~?UfR+imy>HlCX1d9eJ&-=vN)9vCPwP`m4D-zU$~)m)yzGtAhql>+ddp zkDY#rjxoz#H#H0sqNbpYSE6K>r^SrW)&j;0w~$W!os0=CH9r$mE{;xxmZF`Q+FyDa zs?BbBgIm|5Ii?YwBfQ9Ax-f{FpSY$lI|i6%VNuJXgJc{0zMby5Xp8?-kPJx!1@~os zt7^f>Bw7#gst(9XqK>SHfhz&tS>2vUhf;~f+Yc?Jw#fl0yLSEIV{=Pa(BQJeiXm7{$?R6Fp%m!&+*5KARH}SN-3-# zu3R3+e>Z!@njry!ZgH4a;odzpuso>P12SnPX+bV)Y>X*K8^dV$rf-ir888--zf748 zmSW?xYblg@yYElnNS8k?VNIKh@W!f8X=^kiAr^ z@nEW7Va~`sa~0OO4Kr{?v!|CP{PW&<{iYV??=F8Oj@wNG^rc z#m$c|pnZ@g*Z`2JOf_$d1H+0l-{44DesX-$t#KORLPUl z9ul_b6mzY*C~5{rMaL!CFkeT~o#~05bO=+`{A9GgrOP)NmZaKeBHLqJFHB2|Jv>f}$(j1tS?4oVrvG=Hv*AMv zw3p^6UX8ZcJ2zjnY=NMdP-sn019$Io_$55 zawRW3CT!%DV1vg?k$5ndO!K-0!0;nAjuZ_qz(^lW14xCDHPPN?&>wNXcK&PQIP5}i zKQ&hI#IJi5YEW?iUKu^en~ZU92v?<1(dV8>hRkRb?G=N$77@LIe%@!yO011wt99); zMn4xl6v}+(rIhfZp?_@^K4d>8G=#pz6Tpr)x@;w@q08<|(BgF?SLW2^FQ?soSl4K- zI%3a;7xyUu{~?0ce{>B7pPM$@DlsgNMJa|aFhTG|gigE{O#yHzI_Kn5ss1wH)}Epd zYNqqpq)gCdT=-RlQsiS@eERN4{WhgcN~;6XbsdT z49zG}v+oAxzTt!rItUUQB)#+Vum z*B&?XB!Nsq3;BxiR~-4$Q&yWy<$ms)>*c&lCb8(zd{m$$@pZ75YimQLKFMXxb$*Iyh@ehQ*?g3|`{T^ha^JrR9 z37Gp7`$!q`d%ju+G7(LJQWyg98ibulHP+aO%pEs?cjdfrPgfWRP*UZaj{7#AzC}{e zy&6?Vj{sL<%t-m7iMSH0`+M@O{q-Vg{n+xz!8gnv%j3z8v26V=E6*(!ksj?X5!^?| zZ5t;dEzqpxHuGqZebIs0ou3o<)14L{>aqCBniOY*?XG;wF_*PRRyU~Kghm5N3{XI2 z^Sz-H?hFy_PxH1_RczWBj&k^?XY>TU$d5u1 z6%V+(_e%HVvdTe`sSRNuLypxHnm9kFhPfZE7xI?#UEi)@sJibqGVJ> zUsYXD;!zWZYILUCoowDiMuC3@o=1U4RtjA|*60*EzPTVXd}8s7&LpD{w#6i5b6iKDN^ z(%Gu?d5kUbYyHvKe5oY9cgAs4QCJv{t!Y_-0_~&c7&9BOfc|jor%8hce!|P z$51np)bqK*mTR)SFa}*}r)EL@+RRAEs|%n&<>vcBaw)t+zTAWQ9&hK<5ioqH6~3Z4zbHofT*BWGip+m z??dlR*VsG|>gwuZFVkM*sk&*TN#U`|da)WK^uCdicvV0cnc`Qc4<~JbMoEfYmTr++ zUtP3=ikEJ~cQJ}>+l7V*&&%6((A5GHdA?RyKlosEZQoGL$gRtY^Lh`t%e^r=;`!T} zr<=o%5$?Z_iP7#KWoj+*lBO~tnuEUKg(msEl#GIH-(6 zft9wQ>^3(XaJouTxW;e19=(F7+^hLLALTAPwcK6IBSIXidaFO+Tu&S9y1zsP8mSI= z1Z8Pp^xAv2;rM%Em(Ef_8uDC94+#2@lYA(!2`z-Nw#pX8&mZEgtn(79GiY*mnJus8 z${rkN1oRebDwT*@G99LyMen^XktFE{>*ZZ&X#GwcLc6&Ymo}j4Kxi0dCQrO}IPsb{ z3TmRZs>+_}@>?K$Y>RabHntU_S0%GUEvoPB;9Zz6n}~n^XiH-7UHnLqc4tmX*Lm_C z95x3e)*H_Nc9z9D$R2m}B=TdDD_`Q)YZQ*kG?dZ9f`TbtAe(+7b%g=P50lxDG0H2Z z8gSftfqFU9ONRW&6D(5CI43t3rO-sTOFr3E5!Wv}*pCg~)AhBuE6)Z+SFuiEFP_kN zMH@Lx%K^sK%P_{-g3wsx7YtvM z4XSnKz6UdtI%go!&ZP&bjV(_y=LEd92j#Oo*qQg%fc+e^wV* zu~!?N}K#icW{&>mQPY$c_F*FV4_x->%MUB!=3r=Vt57$yu{(YcK=`k7svMm z2H-L9j>0_Bx*}mP;Afx@ZI9spx(C zI>Df~cA@%w%otWEKdVaszO`9urTSMN%9A{P+7)mYZ!{$Ns2~+{+jjPbWF&D6q6sq3 zzR1PJ9zll{THLGGph2xW6>z}QVv=&3*)TE(Cw@<;~%JEpTba+u=Vm@N;meMWHa zc86sk=_$QnXJ1Kd&NFbV55ZP~JTe`$4xM_xL}h;ZCHMxjvlto@s|tNZwW^v99mbtS zUv#;RA_w?cB&}Bl8rxk@N)c9%9(s-#E?G0k<*B?buS_Z}b5^!+o7Hzhq02(W^mrNT z!o?gMAO#Eqj7IXEL7k+H-pKb$tyHzzE@{{1jtrm4y*a=x%>Cw~sNkpt0ifbg-HJKb z10&u@6Sun`bK3^v%cTlpl#;EFLLm24g0Fuz+a*d{@NW)@2^~F!;lwIK>7?ze&NOMnW8D=913MbY(szWf4swF zAxLLJYC242vX&wH5ezpGh8{X&mOYNZ#M&!+!2`g(8Ka^4{3mO683uIg#;eN`1`7=P{JG5kna4+7{>sx<1IqKPnmr;-%;Zj!03t8 zvxop}4rFJv-`^&H>dv&iHvsX}L5Qa|%+GO%(}H~Gxx@MA6M#I+DWwK0voi2!Wjw(Z zs)y68)D#g5O!X1`!BnjW7Po|I>mg#(V}r$ggETntnieeXiz0Cj5RfaN!{YV*vEYuG z2>Mmwe*Yy(qZ6ip(+{ zESXlG7$|k0eE$5|o(53dNP(4sWUJS;NS5RDS3|7^C;AH0{y;E+;WO|rT)jm&r;1u> zLGr3x;qG7=i0%=?j{3}ns(-kGjqq$p7aiR83v4Ayp~7SEgU_n@3R#rc(BmaQR43>- z>W!gV-OrVY?*MY_5nz)E2#HvYE_+5WdgCcOy)?$-8)nN|}0Kv<%>k6QM z7FX_nS=>x3En9S*k*dSdqtND#6C1t0DE3+l`G zR|c0jk(%<6WSbb%k&l-Y`Oj3r{~Ik=>z#y81QowL=;5? zO0b{*^HU>FUR718ZaSn#!!eg31zV_ZEpM0pKSLpTF8H?dK9LKTQ6a8<5A@0YE6%yo ze#TwW2}vm0e1}Le5VuJ9pSS3f0OI91wneGr3vj7eWtxz2+n{jovlU3xy7EV~`!NZ&CqY*C#kQIMOIev~km} zY$2Yke68%}CNRr^=6)Mvq{7rYVZ-AKw-?hM;DJwM{_aCc-~Y}alvt(}aE?yUY5Yx% z6W-iHeGh=jT_8pseq9L%ah;G5+&{{sVPTst_^ETnP}f#=PZaz3H&Q?$?&8g7XX{Vq zC{+jch^jN9dgoUdk3qEcLe<4a6h9Imyn3BH(7A_*uDBNB5Sfs@7E9UZW?<}*O<(Dr zPRt2tN!~)^xz*dUOV3C4LKqLTg+_$V9X?c1l>sV3eK*{?qr6|1Em zT;n!<@xt_b!SQ=0A#D(luj;80AwM33e9yh)aVrAw*InqDud0rI1RdcOSR5VOa2yE{ zhnaZbBckz|$p6RneyKr90SNi(2tRmoq?=0kmYjEbZuQK=S-mFu|MfFD071Av%zm04 zGc%4$W@Pjcp2pQf08pQD(=mS7{&#Q+fdzc*%@TshxM;x1rT>BUWVRcm2Q5>{aB3de zbz4iRZQA1<0ZhOA&{Crjsi(hXBTe_y~ZgB*ekLHG_!7`Xm5 zHMqX;B@LHOH^>N1TEJTc3=)Hh_sguzmb2@Mb@g&;GotvQ3%fyb^VhqS0q?TqRBop_ z4D3_SG7gxuJg@f(B^bdHS*%GFLt}+MUZj1mGw4xZaxzhvBAVyG-0y!SwXxv6`0sLO zbEkmcE)>U1|5mwz+&C_iQ z&D+#mEqQS%?`XBmb@1b^t#5-m>^)QZYPw%V?gAbJw)~BCIFNZ1a0MdXk#u%E2Y?X_ zM!<(f>~uzy3j+`GOCvo*(V@%<*x04Lbboj&;2_7FlCRdFCS7GUhvLm;<+nRidHVyL zGXLLCjRm8pscFnY({J^X0Qjy}wb`>Lr2J`_reS{mUNf=gus-lQSB7c8#WTym#doZR zbMzV!XXzO+78GD;U0}S#_#5}5Nt-V^tyqYTtHLJzs6;lf%+3ZwZS2m{LO`p(!(+q; zdE+Y_oJvavTd|0QQWM0PlWKF7vbTsw`2ZfJ8#pbRj5leka#{hQy=HN!)6X9vljrw` z?uTfFDLm7H6m7q6*<)G4@RcTC}0b@4e5z!A> zTbw^zWWBwE2vL}7A?Dfo192!G$aI$|5L46oDWv`@o%B5{Q=Iy!ogzE@Ha&~(@bcKE+OJIb%* zCW3y6We@5VsT}a!PdRcb+2G*CfQGU(Uc({zvmLsv{U2c-G zZ*#`S2VRE}PyT%Iw3#$WjFUm_=3c>=8Mdml+0MnS5`%zo+p$h>E9%3qrSrMgRDfB# zYl6-9BjP;Zp>(1Z>g)a?PQZgT(c4A+>@;wnfFxJp={D$bXDgE5er0Y0w1(qS%bA2LAx_;)Etg> zUOGB0r{77Lei5lPZ3|;KaN;ogC;kSbH33a1c7Q2@1cD4Ux%5ERUmvX3?aedUgn(tB ze%KyqdAuvd|Iix>6jlLi77yY#^G|Kg>{Yi6PUmyM2yNM?REPL%?<|Dt6p87}=lDp# zaUdrmjB35~0h1-;u1LeN9U(hX^M@0qchiW;6>D1$AlFEmbUIb%#pPa{J|(ZY5Q{K1 zQT^t)t&n4j8t*xuQ>GKizkC5|8gXIgju9X?q@3UUHTC|$d@YcT{rt9bQ`l5)4|L#! z2m7ym6`{gCF?~rC_w;lx$;v!rh`*)%iM|wHZx8Ilozv-SW`iCPg}2|sLBTtp8M+^a zPsQuzJMDMoK;)nI_}7lC>U5-<2%-u}|H88xm%?ck$;$oy@x3J%&82pjrZ7j2Vw7^H z+k|Qh6#38D#f|z@(EW+aS|0k!Ol=w7uC*8ZM2_kF0gB;F1tx{a^#Wa{*WONuV28Ik zQU#(aK$lbwmh3WDF>362|1eC^@)?QuNt~u&F8i7;BFtm>Iwn#Ya=0)Eb$f{c+a-3F zfdXoxEiOmy$r7EQa9T^OZ7#G4#ze&*M`_7u)Is2wUsqDS37723pTi{xe-?Lq1Sm7P zu1qCfLl58hjdorhX)FGm=A{F#gP#`DeT~~XJ%8n-kq}XVu*A_)_ft+4j$r}oxU?BL ztYvnrjs8z^8hlrnIMImsuci{RHP!$J6Db72$dUaDIS9_Zt^3Aj8Fu~)F5VYcG();| zen9WO4ARw*F~wJrz;({>XA1N7R5KNjqb2#pVtaGGZE$)XJ^YlbNJIRl$sOC<#}O2U zZOET6>&}+TF*6kP#6N>H@F0nuSt1RvA;jI>cpoOEqTPM-<#ju5d=Cc4UFSdFhfo!Z z5S^S0o*~x+jhMiZ`_YhRwBx#GP~=_9A4rxzdZ)xLRDPTxpg)Vrf(*N3-3D=G&+_m+ zuo2ttpuY4zf5>gTV7IlR%4sozD)i1TggTe+N%m7LEPGU%hg(vaQzl@LBqM#4qaH2! zzv|)wXPC5d1gHqIC%wG_Eevkv_&^;uEjry zV{k;%`OVet`#>sJFEy9vH0${0K06;tdRQ>0{z-SRG97og6;$mvzP%m)qD|s^BUCXM z!zny7&9{8~Gp;}@j~7Xhu6zr_ljM%15e7(X_*H&^)^OghIQUD*E~lizF=j27fb&kU zq1cxg#zbwI)PmaKRu8;@`u3x8_al7!F{dF;bIvcCs_*wqI}vAzpf9Vw5$G=b42vny zDtv)-4T)yf;nqeNUOlsx#y9TEI zQp0+NZ9X@ILQbzA%Dng@<-d8~7`96D{1YodO&~IH0t|Gd43OT?EVH#g!=f9?7B5sm zJwB3HY}zC)gd!zOhkxx!*Qp)JRN#Wkk>$sD)QybGBEB=v;Z=@grYW0+`(-{f1vfhK zOliVA$+=f&)1WlA101I$vlkNWe)m;$GxE?0O$5Od*Nkskb2rvb<_kwo z%O8@2e_ng8RDg;E*~-*nAI!jOb=?=T-jiDG%YI<7SitgbD^9 zcz*FtlQF7(ktL-p+6u9=GEwV19#C2jQ>+ifOQpe>G;6+S?6$gGH}KxOxR{WwvKmEY ziR6A$n8?Wf2TA#59MR>X2r~JkC^EwodK^+gFD6~K_~&|ZHouNH2F%A4u3@L0=DRcX zf)ZOV>FVo@ZaO5Aco&KA)A=b}f9nDzFo(z4UKC$t(+XRMM$2MCIW_<7OqM!{$#B}; zOCHvkaub$Nkn)MqEdwC!7Z|^sZHbS3ahV0iQ@pXk4tQ5nUfGkMWZ`79gk-#j@~+ye zbbuF8v6tyr;ueQ&Z)3zh{PcA0Z77`D8|rw4)Kzkt!sXQojwQp768TREE#K$=Aos+A za-znt+*5caOo^6JAqQv*F^uo;eq?$ZzS!(R-TT5llmv2xbg;Q(zAfBKyuj3$IkChn zfe?*nDemimu04H*kSEHea(1`;@jLb64!}b5D%N`}o50)y@DSMcsPT&9F<{Z4W{^C; zk?b4t!j(y6LHp3S9ya&J+516@*SErhlRmRHj29s7(?z}_DDA4K{w(qa2Yxy9>e{0r zq}A(q+J1T_3b~~_>wWF%SCaAmIuS>!Du4p!LwcQQg`}BcmY*7OJOUjTkX+V|E}vZl z^E%)H(JZJLe#Y1QNb1@GN@u0kSH>@!KA;CYq;ZOT3TvgZfSYr?{NO}ZGF#L0`Vz|? zsTz=o?MQzGv*4#Iot*{tCUfMYD%JvamJzz}PPZ!ZPrhqbxp@JUO`I2610IhH3OGNL<>UVA5zHLX3N#L(#E7%&^?5374XYDPv0 zj>JdlZJ{TI2gziVAM@uv^;s;)2(wWBo~}o)iW5f~Z=ZeG%sfZL|E@+~3K7#E=uxd! zDz*F7IbVmqVWbb=1dUX9vAgQ-<0aObSpZo?MWogmokc2vd~;^Idkc)rP|kJ{+(n(k zuFWmAaI%=@cG|WM0R%R9wsIWuYNg5qvC;iFl_}CzTbjYg$DOUWE!aAHjESsx=fGI* zBPET@n&di-9CRh*i*{wllB-LoBsK_fD{Dc?KBJh^bv79Dp7=;V<=BS$(D2g*cGTy% zZD)~O6&07Qn7;8n@{^cb*T5!+syp6J+si3s8Wdp@*u>7wnznYmn>!56XGRE?T zWNtCDFFMWGd=4g3{gZnK$18%cN4cOyr~Ji2**=861)kH&WigNYOrR|+jSt05x2P*=wmSrbxMw-Q6j*{Pq}x370M;qjwv4tb40&q&);zT2ltK)} z_@M2s$3otJq-V~KL^5R*<@OAJ;6=M_HOQj(fk@Y*GTlOKd@#EJrIuF)2EmG!iwOoFN|BDl1 zZZ7B8$xA0SaB$Eu(fisyPA`U3*vk(nS3BHy3F{Q0DXYq0y}MEC@6Z~2MUKpP`JmB$ zEZ|^wZt9^6cjx0Q<{RHvS~X1Ks7l^vXa)L>4X>sLC3i9q%YA_;!e*;~5%QYw^4Giv zuCPH9uqQX9Wu;}@{PPaM_&O-_UEc^s@oFzn?U!Uru#g}#~zE< zl^&bhIDb`jm&a*uR^4rmEoc3|Qc51`qZy57h+>G$4HSKE%8xKof=t5*GWUJjpKE2_ zdAe)EKIx9c{Y5+E>ij5|0TfM%46K%*C#_ZIhW5gw*N2&8s!s(p1GU*4C=dsuIPkpG z*|K!IWd_@HxIOTr2Hlek{_8kigD@ZBJ&I{Q?UUKneeR$T}dDL^nevK-WG-{NE9i8vZ z@mMbs2Y$7ggMGO6*#1$EgYtw3WzJA+R105fz_xTHfmSh{gi#N^YcU zPZiuuQIe9p{xqjRp>pwa>)oez7st|SOsY?PGvcC|trEIO*IM&M|CHUw|Dvq?eWt68 z!(nT5fO>{p@0c8N6r7ir_by_T2d16xViS!{Wg61a&lgEbk5*dq!e$XW6wJm6la*gT za~x^A>F~C20KsxyY0W&z#}EsCNTXq04Q(L|35{o<8X1=QF`Ax~L})Tp3c*v>R^zEJ zG#QR32*UW7{br&l1pgY0mYxo`YXkIJrAit1^7~LB&(#jDQ9nL^&{<59Ijbh zY)^RM!4U>_Vx(7D{_I&wOUUrSf&dKoyo?5V-FuL25kpB?^)wg2HzBV@FFrjt+3JD~ zb;#pLXnlvWl05|OFibew5L$E+VQ?UY`g9_@il^~LVdu(Fj0|hS(Gp@U^af(7Y7eA! zi!~yUqm+0J)TN4ZJ~7iMs&vuCpMja{|IAnEa*2oHLIIxgsjL#w^Xzf~{_MDteEebC zlK%_x7YpteP}{qbX8=L@6N@@_rMX9l_vOV2;|`BSxS?1HyJJF>#T4)(Wbf?638K0Q znyr4<-e=EA%niTSWjy(m46w(s)=~M&>iNLy4$vP4XEACk$cy$~4HCB+>O~8Gk7s5S zwTOiB66uJF1^mkK@+@Jq5b;(%1N>CB0W)NTs~mU9?Kd?|0w$dnQ8+HMZXIRT#;cefaUj;CoT-F` z3?F(0+B7t&fS8T-;4G|ueJkhP5TC;_;mam7N~a?fSnqA*)9$DG!q!@i#0bd*m~qij zJ)hCM0)`m}qK+8aW;{q_(GR@tWvBdPcV?SF>DE&})IfYYJnZaUzh`#we9S~-Gf zGlJUYNOmA-6kL~^_24H@ssFI3!7J{*&?_K*UKXMOv8)3@Xrv`#P_v(o7if9|R z?KoySzl%>4v=#F!E~(?kPKz`!e`}t%8K|khTs&^e{!k0*E+Vk)8Pmq&$WJo3q=L13 z*r`SvY^09&#&pIdXg)Z>=o;+pud{VF(DYDR%L;;k_0tsm@0USae2Cn`{XAWmJ__qb4v+2s7CPyH+~Y7Maow; zuKY*RtCaxtvY4pxFOXdc45|6z=a1AC>c{Z!g%iR$IMn~>{P{!lC}-HTZ=oJD%rQ=Q zt_%}eB@gB3@or~LOaE4o?g#|fpEVEwbSC_HzPNz!+3%&EPklJbHKKS;ZikqFI)^V6 zY9S;S3D0pDPH(+KBJcqc8X`G$%FH(TTdLPs0ntza2e>{sz$3K^FHauGmoF^n(iT~N zrU)HoBpCkYdH!G!9se`uPl$3KHjUloP&zMc1}J(!rJ!GxUXyWSF^;^{+7+xm3TX1( z9Mx76xC-f(#aC_ZVn(SU8g!P7={2dZA&YhHIF(!QmDzaoRy#FXA^HaF^x9^~ikz+& zcHUbi{%nWbP$g4Dx5FzK!1N;oNH^%3Ml-WY2;6`E~KbmuF-?LfiE29>X0l9J(&Z_J*KDRB9 zb(k((tS}m1H6Q1OO+Wc}Qt++=bdJj1emdwj6NfNqS7vGq5)%rUuni0hgv&tmnw_3( z^v8FW%+)G4=+f9rhNSJN^2%fThsF=z_tF97A?|d#VA{l4L@H0%bpQ7*Ivd~Wy%8d1 z){J1Ke9+P)Fx{IaWnfXIuM87s|DR=ffP^kON#%C#fmN2?|;tTS zFqLQZFmF{X&8Ykmj?xvP$bVFCcQcQ?I_3grdJTbr3AX6WOxI{QY~3JbK~0YK`SGN zx18RjKrGR9h{rhUoym3jdzPhU`)Hl@k>Z)TJvE)LoixEpTh0K5aw1cK#;|1Gc?>zuFAFEn!=K|_k%gu?)uYxHS#2cYzCpO zNRw5S=v=2~aTnr1^;;myd|OI)urFQ<)p?ikPR-Q))CZP}*>7O=W~RYOM`m)4-9BEP z-KJD;@Z^8je7FkSpRSih7NNMiV_*}on6RhP6+osTCUS4}2#^6+;mIt=z$>EIXZVr1cR}sQ zOdja0$>J%8dsy#KNeMh8pkrqzTiIZL2H5jhAj=c6;q{EgCClOEeq z{)biStxhl`_83(!kH~rG$Y)3Zbhxel$Uwj-=XuzL85nnIgiTl8zp6^tDqs2uEhnk1 zIVei`i`^;(6_4%QJy&Re2tQ7^qXRZs6}|jJVQ7(UV{wY(_LrCG+WAoiDNz8aLA=CRlnMg;n#ieK+-p6A2P&bnyq4zexgSIqYo7J6ke>czf|$vt;@A?-YG}pD#GV6w@C`fRGJFK8L05+33{z9ZipBa%8HSyDeXwkf6>r z>1|9l3Y9@*_S%8&D3s)fXKF@h&eXH zaivE)3-^=dIq12}E*JgnV2|$n$PMZY#@b#e4w?+t;MscVc_B9thYJyZ=W%|h-vrp~ z1BMQlSZ~W6xFAHW6AI| zk|sfg~uqxuruwsgFg zXNqQd`^ID-`fiQChoJ#0x=G&^6l3E$D9ZTDFS+swA(LK%N2I(y^+gmS0y6FG=w0|t ziT#9}HU<3T5B=p(e4$-*B~IYp2%ZVJbOHK_5*QKrMX#CIX11z*w%TfCe?KZXI9Q({ zD91)^0oRMDgKZLn~z4pr{*k?86690e904OXR0&e%e(QR$-2SyfhLCi2Vge7Gm+fHOL-*1xd<}!s@&_^?9(6;#Z_a;(@`640 zizM06lwJd8bW}J?j5dL~$0dRT+_ys+t~;1gYB{up?zx-U9$bk$hQ&f&7s#_3tZL+BKT?x| zqpqgjFRpqXKlsG_7O8y6r}S;3(Jo=+I+gQFC84t9%5qyEU6szU?Br(~E_oT~sq%fj zsV&XD|C13RhuI^u!4#Srpcs0NNhbsxo1&!SXldNOb#zb;>7RfzqC0um^YYXXe42=X z_d!8YepggMr}5!8+l7w2HC7SpS82*zcR`{2A|zp)eqbFaBD(kXfy?g0{LLLuj9wEB zQ41}#dPdxLoImb)UL*bsIo6?uMV|QQCQYF(^=AWe>8-nQCQ{hMNmUNH_LuboaptV; z3$Awu98*`uwuVKWVo~=jM}Z-Marq^bsxQ)jdXRFhA5R!bWg;|pv{lM{%_=AI&G=WF z_qkl}=j*U+ZEbl0D{Fpf!lp59JLf2?in;8yROC~v;!J>0$zyhH9@OATzq9G|;EMYM z~^R=F9#BN zoq_FvouR(+PC6c*Gcj^-KsH*68^Tf`Ate=7a`rc8ZB-EreelW6%?-Yjw2ZBTU9&(_ z=>tnqpf&F z)6#@(7lDQ7B`~<6skzyHe^F3b2hi%e5(Ltp$wvbofyv7qIY_BqQu!0+q< zowUWxM|%Z3ho{VGopEJ+Z`f_dF5Uywk&4s$gC7J~k-t(Kw~~9h&y?{PHHFdk)96tZ zHd|*W`oAmaRy!}~JOJ|Q*Wr8!Zth}pRA9uInr^*40hiSzK3P-W3`;&{+bLDg@=B-F z_Tr$5II)U2QPza~g;E{|a3Ht};Nxh9oi6Bbz8@v7-Ji#b-0RbR+3f)3>d{=cf@wOs z$w31}10EWU#^#bQK{*q<381)r7XQ-N+h(7~*35o*bJ7_baAatfp!!L@MTHA1q0VBI zQrb`Ps3ao&9%ws;gqns@jW}Xgm=4C~yx^@AM`tih@*MF+hn%M)M@}q@|;lHWk1B-_b$*gDfmIq37GHlz0v3rav>GQ+FxuYV2!(Y zOq>l=huh=j_rTfR-THp6fqrH!6jbV?Fn>9b{r~E;RyN038y8mKDd)*qV&x@L7F_T5 zDpLT5&HgB$Hb-++0Ci2s+^Q4IcK}fa@)=j2dZ058ch9erujyGe~9y& z(JwmrHCpQAFzNEex3u!Fqoca=7+}(@D4~}MIv0P}!f3QVb0YQeq0%(p&Xaw-a1fpF zX+Q5n%7@_O3F-;AjD6fUDuZIgC~XnBARdY6muh1 z`XVj_Iy1PWs^xnMqf<}7c;VIy<;Y3`uDCa@QW;LsrDo|Egrp*f7&R0vHyoF4yhp~0%IfB+d+tK;p@q(~%Pu4wzP%*10e3vFStPs0 z^DuPjLu$I4o6Ofh9ZV@OXbI|506y4_s@NlMZy|)*z-x;~0rDex$dcn_*SqJQ;RGzY zuhW7wX@vSeu|)Vzij`ZRKV)Y;-Jg5#d+g`hg_N7Yo0EZPK7l8{ml(S&Rj@-Q!4ReO z0W*e==I1Yp2qa=vShh@&EBTAsNDEsuAf`Sn&`RTi>M+ou67K=oO*{&KS^qO`C z?fS<1Nv3v~1|0iH0irap%w zq-y1U(JNu_BVg((ny^w2RUDJc>rG#yuD@2hwsF?d+Z&2n(l{4Hl<;0kZ*Aw& z2H>3kn_ZH4@qEh|(07m!`AvDV!}ixCHx~VRVsi$*WPQ8}+`Qx$^ju5e%nca;SvrMN zKguTtZ53V49nk6pc{+9+v(5PkQGRu?My5^B&~xP`-YZY@wSgH&c%?QvZ}?Xr&Fn)v zyg!Kk?aNFH>Qbec_1M%GRWdOA5^Hs=Nd)VQUb&q0)R_3fOoc#(P!mb547p(wbuXZc z6?X9o{UP#qSq?jG4`PCP_tD*HIm2V~^MM@R0vaB1u5Dzsy7Z-uqAZp-n4*rCk?EpNvrotZU2Jr+WoyY8b2i-%GXW>8 zn;Tz#*9k=}X4wAt_0?!y2%KlOBFmvjt(2)|!Sf19gt1_~CrX#s-CeFn=~sInX)_QR zM?{jDAfdc6xLsKz{Kc=@;rg>*i;pVECmZT`posC!0I226w(>qPNh?i-T#*AkC^RK&w}16R34H-Ip}+>?tsCU%^s!9Bb6EeC znB!#S*6_!&A-LnSdJf7cQfl(Pts?+nb-$FFJ43if6+?@%a7UY7m!<#-GzCbo`^@B} zGX7DuD!6E0kpuS24w}VVNP|MEZ}ZA!fVxxXb=jtTH~wWsbbO%(gm{PC6lPf<*yF+ahw7cby3)!0uOoL{Re0xdjhUB zcSLpA(gkV=5{)cO6}4Y{i&tzW!NYzG`czoB=Eg{pA_mPy7E3 z_uFk~lv->1TigpcttxkH`=!Y`S}H+R$2&{-alx7zhm98C^Kmn&4#C4%E}g(K$Rh3j zhtoiGse#(}x_CEyi7XiHPszNSyl?gDc#=5{pLW#ji7egq2O}+Hb^zT3P?^YiDAr4J z1cCM#|S+c``oqBbBo2}WIGaJ>k(iJe1@wI&ny3^rsOJ<4W*{>M^Az6XUDKPKEo$g zR!XwRq`V?m!yqfgD)Y=sY&?jV`a3Dr)%-gv1zD${#hmA|kJs0o2@VB_?OcnhI8Tbu z1YV=detTD+>H+N9YDJc_5Ks$LLhQY04Is!*Y3ry~yWBrLSAXd1)zabHB$T%`tlwt# zQSkSCLja0%QM>sCuP0}mjS*6zpU+SiUAN=@VsV*DZ{bQ!;|rKH+m9TcZs2QDZZhKl z?1p+e&K>UqW2nUTF)RGixAoEFo0otofF)T8B<_^o9{_(K=+76Hek!n^WNZXIkz_p; zH0To6@Y`p6p~S7~iBCOPyn+C}gXf6M6N^?rbFd-Hgdk-ecfVHqqDJKFCDftaBt#QR zYR=JdSCd6wbdX^K!OZ+Qmbx7mVvUaTS{)fMh5v@KsxBG>f(Pd&ejtIeJ(^WtZ^b&J zCIV0i^v-j7$v5vmTmy^%i@6q#(xtkXJ9p)`L1RXd95}AJ1p_lW%nBp*`H#XLIn6S# zWG-0^r+rfzaXJZdqMrtI9j>%=;5MIdc?F^olKHysXB)0@;%VB>OAMw|13SP_g&d5K zNUBk+95Br=%P4sj^*HULwRYvUzoqp(oY&RJoY;Uw1|80HNB{b6@XgctT9T4km#%f` zHNy-69?2M*?Cz^>?7WuFV8obtf%aN0@@kw> z_1NAS7o%90dvU3tM+lz0IwO=5Ys~$J_pN6@iJ>9olcV@B^X^G672w~KgS~bo*XD-y zpOnwa=98@Q|6+W~vhEsDC5Zs|?{CS$M-c~WSNc^)t7&ex;lo$0Le2JEhr}7e-Ynu{ zHO~afokk&`srzGFQ>anPNtCQu4}NuC8SMJrT=*gIBVrr(V50@By@iX2>2e!%P`IJ| zGUR6C8vHoHn9vDG2%w%Ou+l6MnR}8RkaT>O9s$PLtPGnmF9SB8IJvUR=9v2xHNu)$ zR}Uzp1Rb^*gE{D;5VC9P$A0i+!1^L05^h5dPibp@5Y>%;6-S^9rhxLjG?N>%{9sx7 z2m?dvt|LeJgx;6euhM5biuqX3^4e@Z*0qPNAg++W^CWPuSI ze{z~1F7AyrC8N1IiZMMe6-luUS;#F|hSG&tG?cwhkIvyR9M0=s`*raffTyuK6i>S$ z1>5K+7=J%P_!Bd1t#OKWLwTqlsDQ9=f}8AhP)DZrjYdk}3Y4Q~hpqEF^LKP~M00?) zbH+yhbN!K#02^I8gsTAOAN{-Lo&1Rwg!##B;?N7dMwe%|Egk`&=M}6o2e@kLvpg3S zdyDl;sPo>3*cAN<)K>j(zPDx1-GcTXL0T`G=at(TfX486#(#PrpZ%R;P!5B6H;6pv zyJO|?E061fPZ-CYoP#p85IRf4E%@cREXsiV!%>22V<8n0k?hdwCz(==^ZwtHlED+S4!2 zFWl-?5NfEzw$ZpP10LIk;CoAd$moGq-CDP8M7c~v;2#I=`=O8 z2yY`SC8t@#P99KiEmGQUI(yhBo%1j=fu|F`S14C9U}A+YFW(n+^QaGhH5M317>~xkTArcokgTML=m}EOos3e0eY*Jq1ZVdJeD?)G^ z`Dd~Q^&_~HA15L#A08pDipQ+rU3HXoLMS7N?4 z_p?_}__{sMUM>}T3_6tm)Ko~sW^4^07AX;Nrf|j0qo=pJq3IhNuf6fS{w9yb{X%wg zKt_5y6;4gn{cyX+&WA-h_j8zvWz}5Ro5DSTgKLt5Jrbr_?kzmU61FXwBp=w{&L(1A z_%G}IsD__9NG)8r?rerF9#CdrBw+{)721wte z4PNznAhYVTA{PJ&4X4eac_^_=>Gn7ND1r{hzuTh9?pJIe1D>S-kW{_P0t)=WU?M;4hz#uFRByX3^Lm@K$=U7{umn=AW73Mx7yJplsv|h zibu4vZxpv~a`D~%$_H_KeE#l8=Lmg2M{wHNL2Wv`d_N4c!hvhstkE=T@hj202!JDI zD&D@D{%S^ZxHX)Q`#5a)_AAgq!ODV)fyAC%8@cIkn6tG3ze1bgodr(c-y&QT>38m_q! z*wUFAVWhmyn`zYOG=CZTB>{*$;J@s276Ro{lpT40lRh^(!}) zWU!eBerZ|x>cZvS3iOqQmh;|YxBL9=lqp>5dtUwsZD9KCyXiY1Jett_lSx;@d+(jm zp_uNEQbHha^Sq#DNT81t8J6x%;0pV4;%NBSrwjav(XVV}clgJQ~8@5@T)3zGdo$umJsf!Rk&658oL-4A#Ul73Q!NI&Au>+2%Myy`^ zpVq!QF3P6+TM-Zml@vrtr8}e-L_(#zL+KWfUP>B7MM6SY1nE?|V`;=i>1Ju^W&wfU zaLf99p7*)`eEIWQuDNE;%=w<0bI$fcX9j_D<#jMKzQ+E-tdnw2Q&`BTo-d^E1!ndhDriOJLo%nX0+G5g_ZFK#vUeQ_zv) z{EKgapc22MJXB;bvH98}0x+7g93a7twduW6Z_v$f`2W@WadY`x-%s%d}lj5vX7JV$XiD`3y=u zg(YNR{@p>b_AJTyJ3bbZ#ARG%Ka61F-pYTrK{=?EE z2}Wc|YS{$85H~2+BKsDp7R?&guKH(WCS#n-$$<##^77D1lHBN>XDCxte`ipuB=etX zk@QAff@c}VyQp20g}BUiss4SQ44$vsx)}1nv%ZJvTt=@$m&_Q|&yx*_FhTWaJy=OY z&yEtzZd931nF1e%{mP;YJ-gcSOYlXTK8jO`U?up$Wxb29rZ(nXh=t!ZjC55`1_pboPN;^3XY&sU*;DSe*4sonlvFHnaP0akx zlarHv_3;K+u9L6Uhw8^q6g$9eS0`MeXf^e92aQgmSXP~d(@AFuPWS6e1x~(a14+{j zo+TZ2s(Iey?a`&zF6f;l2HYDr<6HUAc&s zplY|;Y_i~X&VO$W*ei<{cAD**ISLAK(*Nu@Nva%i#jw(Y6}5vSGt&| z1%s8aUScHur7i0@ZHYd7bp^E51Z88;FOaY`Zt4_AJwGr;soM?}KSMvyzS-M}D?4Co zN9f3`&bV}+YU)u~`+dp2R{|NC?WXCDf5`2zQKc@vbgrC9m zGJ32f9Y3TRVmeX1!d&fU8v;c*8C@^kK$RRt3>k6&saiQZTqff~sBAYah1}^c=(m(5 zvM_|N!Su%r1ibgBpWW6^JiE%kAQ9U|>d1b?aA(yvDjtg0fg$;JO^Sk7Z9@I~-*cMk zM~3;52m*Si1pY{uvHs-2c}t}qcBo%!%T9(Wcu&hazi*(e8xw+)K_BAtnp1qOh}fCz z>BRhTM9*7yMe#6vJ z`YO1b^UmiP?*$@|FlqZCON{BI*J)+MvwHSg57L9Tbd;p`Z&IQUkc1)FdE9!ApFjHu zKfDVJY|*qCImub*7(2Dq7-GbMbv+8Tkt%01L) z5-si9k<+fmsDJZ zdx-pZVF;F3HsrFt9Jb1Vd8BfljLVhB#ZS@G4^Q+{9CX!kOF`u4v+3gyz+*!n^I4-9 zczCEjnG>`_j~lfY4@Ie6DQMf3W;eg6g;r8sN!4~8=3~aj!^5krs%{=A`ro3g`mn=c0PkX_b`Lb6p$?8E5op>7QHUZsMq zSh!9Qm3SnFr5 zUD7ivs|1S!ayisEQ7tuP#ai3Il6K=~!F)Sg)9IHEBNz%ve467KZlL0N;2j~B084#a zws)~%xAz|`_0^-g?tguV=1TG`KgH%OVVfGx{gZ2y5A55TPP{gKU^k}sCImoe z22;i(vX!Ty^+k@}5EI-&U7oGhJ8rgRWJlu547m9s2{WwgO+WUMaSpPbD8E7};2112 zS^0vNq~=w*WUX!VQ080|V%j@odaVS*iXx%7z&r%`NbE-w++CL7V14XuhRU9jsR_1~D*j4Z24vAcAHER?J!c}qC z5TAsV`AXK1+fQE@5QZ(Y~s zKE}22ZIAd4TL#Lur0P{1a6KE3m-MQWPujZTx{4!dz$lWxmuz4Oib2Vs#nSru(pxc? z;4;vliljO$Jv~acJv|1*S06C}6o;WDACecsO_3~49?WCLN;B7cd15a{@~NvsAK8ud zsis1hx5_~7dr93^^9%Kb$(RiT8xJPpw$YS7vNJ~_H|e}UFUGF$eXEMjm~| zKJHL)KjXSfO>pP6;$6|+GC2$UlizY|2YRonU6OZJNi%{FD$(X918p=QJqe5T_X+Mv zEZ?v*)2mmnwj5!F@gim~KZzTq&|HXESbh29OP6lRJ&}5-jxkCKnCbUP3$svGR$cPl zG?V9>Czaedqg8kxIE|Xtr|p%_zJ$8=eMLhRzqFAWc@Sv?e`x@K7w;u zqa@_FZhvYd`}zdUG)y`Yj5alSyofCAcJHp;1Sjdc++Bz8Qs$+}JWj~!&@DKGGVQ0l z6+O(ypOVXZTOSnYrl9mO45&zapyK3f(_fx`CK7yl1)G+c`I>Xq>*ij6Z+@1ySJf_% zS9urncG*Tqp9LbvWyZP))C@*_%h~##ERwDK2}6op;jz5Lq0_u_xvfrYA3HNU^r&bu zkV2dzAnb`_f1v?h(qK_QMn;fsYFlX^XkF2pu0<^+V;H;A@b=gfNA&9MgG@DJJ+vTG z_Va6M&Wbm;3foX}Vn1kq%j?YC!j7t|aZSyy@<pyqcpFILK$CfyF)WdvLm)OPzVe;`4#Kq zM{7D78b4&;l2;t#g#yI&8o<_Ke`hq8XMYD2!DKveTd3gYQJMeJkT1>eIJRbhwO<_0 zE`yB8pV{^`5m8Fu&;2^Z>j9g=XIrX9q8{5)lffGkC5*x@yAr>C<}!X4kRQq`l&&Ssfnoh2n6AF#$wcl`&t|{M0 z^{Mj=uj4yCI(E2&+Phi4fzu2w0GoE^>ma z>S9R`tnh2B%TZ=yZ}hoL5={+jU+k`SESA)zyn7egIABvu&qV&5PsMg{aL_$V!KT!^ zf?zV+Xe#yA6HQGrsp;Q)(+;S;Y1)?d_U`@o#Kf7pLIcyKeAU+Fss}vK+oj#wLKh2N z!U78o`dHb+G3e^BHc8~Xz%C)FO61uvb>*(;XilKUGM+5r4YYn3rB|U^>^9}|+f@+L z;tWN9Fa*l1y>NC3iiqG{78ZeL*c%LwX!MOp-NfeG+bYsX-SyIyRE7%dZz3y}mfVhuSh}X&IOJ7D;}H z)7Uett=~WuD{_?REDs!}TSWrP-BH7u>+G~X9F`_1w#T6jSr;lHjrciO5enbp+=CZR zcx_E1AC0tu%J3!~j8}gAF34mVvt32*v=T=|M6_pgf0z%Q1Gj2ktR1;XNlV+DN3b%o^U` zxE6PoGNd`&oR!%o)w`QpR436&13)J?xoSeT__+9k8qI#RaRAiHqocHv?GF`?Z zyEfC};rQKJg?ZjL(q?mNIUlItS*l*aYZvmEJjAc+(WB3q=1RY`do%Zer5uEa_0QXC zuM#&i5Q5P`CtpWCdipdR`pa_Xs0_qJyi{F-5wEJBR5Vzi`U^PaE{H|qdbutH5vGD+l9ZaY+@(LI)}?Z3Lh4fBjCYt0n;aVOZT7)73DSV-3Dx8Io7~!M8(F&_S)4$ z;l%Bej}5Sriv(;gEHIJ>=Rma;?9!6a3oW1$^9;OSFWxCIPA&fZ+k}8H1NNQ6Zwtfa zVmM-+d!1#>T7{rvw-=uHxA zh=OV8b;IV6PGxmv$7WT(1?_2HRrE(GpOyVJ^3zr=K~EITr2VA)ik2WeYw(HAg#=7} ze6F8h=j#TLUd}7_v7rbGhvU(i|F)Y0k}Wpr1O3L zw4MiAcwO5c08>;0S@hu8u*mbNb>mWpAU1k@Ta?PT)fE~(`vWBqVmJ?f1zv@GgxUlNhLih z<|CU!MT7g80cI~?_q0OiyWe0UdjCp@;1HvhA13YGbJ6})(*h{aT=QJoDSJ+Kn0+x-3tCY%}L;Qw!b#&^gs$cQrzI<^Mblw(ZV`J&q6mmWyDYZE+ ztX-obsl^j_M>Lf(6PpPR{11hNb;iURJRpD&H?HEV=GfYp&}ZqYmXT&`CJc$fW(xMV zOzNifv) zK~YkbG$}_@b92s$gxJ_1(6?gN$e~}h^ZosummE*&VNYv&$sw`BthU4#qRIW-F|eaI zCKe*YcI}stEoO^TBB#B+p<30goA4~B<6!m+{w5FjFNNU@XxCdOb5`4}X)P`H`imBW z8xTek$--sG3inT4i=;xJ{cm?Tvak3wKlwuPuAU!DpVRJnYf)gGq$$+A(XM>~p%R6L zcB*BXEWRmV(g?4Zh;?`5hO&Io8fN&jJijfRb7SE{B-!z4ATx2h$waWiO-^Qh(4g~N zgEmf}wjL^s&7zZql<1_0deAjIjbZvUloyFqD;m$g5c`ZT-gKt&s0_EPy zvyt#iVXTucr>bUerPr<1gM1>W@Jqq<$*1n?&wuUvI8+(dm22MJ-T_IqXJUQ@NdonQ z(n6pg_Mwy3bhsJITc8fLSMO2wR=9D3&Q~()?VE?X^xIm9NTYZ2`pis7Xa4;Ad z?fU?2TK8%<8Y6kxMDJL9Pk~R=94KeGvR77BHMWgbHxjepBX?G*7rC6{1m4^^0RUl* zS+r3v-A(2&3mPZJS4_(S>;Cyjcx?7_v!MGBye-W>hHbLrQVQ|u#XU;ow6Xyt6Vw8_ zi(=P#o#K7;N%p{gb8qK^&(6ZPW?x~q_fuD~Hd=ROIx(=NE5(Kxgovu#N`{U*?_cfzuF;A>2l9Pn3UUfP1#BGjz z321j-e6j1>&IRC)2O3T@l9PT_US7VK-jWe=8x@A{^_-dzvXOBw4OBK6u5l3eJXqm$ zK;9tdBiD>&HJQBQpkx2m(0k585hd!gTYQHWv`HFra(&c@>+4Y)|MTf@MO)-8&gP8C z21l`(_xSOMU_`*#1nco5QC!-%ReTZO>l*pFpy>(2nakE+OWN=sKQi#c3wf<$V6Ke^ z^-vB%+>#8~YJ^@CGro_Gre#RDMepNb*LD+v=egjVGo=*IV~0&dM5Iz8Lm*{Xmq-Z_ zzr%HNOCW77hg#%RWYX0kAYb-|8I69`D&sD+q2~9*_@VgB@YZYHMS$fDI^9(-8AdcYWYRnKDUOlfG^H(?qtu;-Fqv*Y!&Qmq1ZV2Jq7Rx z-(Mcd{i7a1l=I|)_X)uX1qu9ES&GSRr(#W<8r7CzMYU@--&pUE?l%8egokuRb!xDF zNOvnbaQwAx_B-!k^!TQbWhi4>k)a1OwA^ynt* zX_`hB!m6GdK2l;%!_2IM-3v-{beo()e5o92N64)X984DSM-V}Xj_zmK$fb_WoIzjQ z@h~(r44s?QvN7XJzkhreX?{!>@=j)C`3xcjEZb#QyNzTF_g@{>_)! z2H>#c!n7NE^+YX`lpJz5SETW0mu}pB!&gLQ|f(i7yroJuWOTnk}{;6D*5JZGKMu_ zw`Cl)zMm+^N&UlSl>mV=f-N%dDyMniVts6ptr-pJnZ3Dr`1G3IkI#1R0z$;0L!5%e(M6fx#0r(5)eXCkhmZq@ezGa>)Rbcp{^EI&R2ilyk-d`bTe zP}jPrqDSr)XH0a@Vj1&Ef|82}y|6GgDXVVt__)5JLrh%Ub-W1NL#k6?u1HDAG!M2h zxXJj%$5Zk^Cl$ltpwz>BguXfF@I);|gxA4FQ;vDhkS-zf{rLxM?CcIo;Cd!F9`8k}!512~k@&D8 z`L-+QlkF}8;sx+-f27(Y2`a@450yj|5g4Ml#*G@MNopg*^4Izstepi*?ZoXH)Q4+s zf<#2Gatz@=atdm;DZi2Zbs#dGf2fB3KfbFD{$af1g~?2I(8(&mK>Ro@S0kg@r&{zc z0ZKtcBnPYa6fQ$AN{78sH$*!1mO3wpC|0LsH=(51`}lgl%U8JW)JT`@Jw3En-Y*U7 z<=1jApB<=m?x)h6xR%2}gYcF{!r6CWGpM6(!lkok;tEP?j_pMT6;$FJ+YcR0>3S^~ z^q2e9^(jYa(8Q17L`PE!f^+N2y;SgElAOmQh*pU&@0W&~9u;!k(cHCL8MIunW~g0xX(+=IVwBrUQ)had$_c9lr=Z^>WyCsTMVmmmn#O2(K0DRBB#Qp?9In+}%uY{;Busz+|?3qVo1#ym*q3vPc5ms)|6bZZgZ!&tDX6`IvXX z9n5pV6Y}T{4aWnrjxH$zFUs9tlh?#*$TyY>7#RLzDy@OogZ0#I6;W$RDrLn+Q&0q< z-xKabGb>n}&l#K(eSOa-uE0v_2x2Q=;BYTUvK0=%|vA@T}=t&F`AI>kV20|u; zw?`D~4scn~K1UxwNwK}H!{TlnA<(?Qpo)w@0#k*ULWZ4<4Op?bT0_+U@^EZca*Mx| z`^RdSMe2Qsj}IKK)NW~Qo&B$1!m-uxH;he8#p|w?1GU`aN&J%k5>Eh;(n^j({mA#U ze7nyvCI1PZ;9eq>Qb;*w14-BRH~IP53Dng3Eb71dD$2<{($zicQ`++0M+o`v{79F* z^wp1zkmu|$U$v8{@O#XIAqsD)9=iC-dC(Q1cJcb z++aNOA=__&Y2<0sZZEr(@q8F{sL9i~?S>9goMW#91jGPqMbWGUM8_@z04)J)O{u?A zV`|*&w7CH4b0?^T19-?41)dte~?XIHGW3Z>?22~OW^N`w4zj@r17i& E14%&51poj5 literal 97953 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

MB9M(Un|#h>p;3Z?iHQkh_KXJ}JgIV9 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 +`getTransactionStatus` Method -The getTransactionStatus method is a convenient way to retrieve the current status of a transaction based on its unique reference. It accepts a `transactionReference` as a parameter and returns the current status of the transaction. +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. -The method accesses a transaction tracking system or database to obtain real-time information about the specified transaction. It retrieves the relevant details associated with the provided reference, such as the transaction ID, timestamp, sender, recipient, amount, and other pertinent information. +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: -#### Parameters +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +**Parameters** | Parameter | Notes | | ----------- | ----------- | -| `transactionReference` Required
*String* | The `transactionReference` of the transaction to query ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| **Code example** @@ -380,15 +386,8 @@ The method accesses a transaction tracking system or database to obtain real-tim this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); ``` -#### Events invoked - -**[*transactionResultReady*](windowsevents.md#11)** - -Invoked when the result of the getTransactionStatus request is available. -**** - **Returns** | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| Returns `true` or `false` if status has been requested| \ No newline at end of file +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index dabc7c4..c1b88c4 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -146,9 +146,9 @@ public void deviceDiscoveryFinished(List devices) { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("0821032395-PAXA920")) // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too @@ -166,11 +166,11 @@ Instead of discovering terminals you can also connect directly to one of them: ```csharp public void DirectConnect() { - Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); // new Device("name", "address", "port (optional)", ConnectionMethod); // The address always has to be written in UPPER CASE // It is the composition of the serial number and model ot the payment terminal. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 api.Connect(device); } ``` @@ -178,15 +178,26 @@ public void DirectConnect() **6. Add a method to take payments** ```csharp -public bool Pay() +public OperationStartResult Pay() { return api.Sale(new BigInteger(1000), Currency.EUR); // Let´s start our first transaction for 10 euros // The amount should always be in the minor unit of the currency } ``` - -**7. Add a method to disconnect from the card reader** + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** ```csharp public void Disconnect() @@ -195,7 +206,7 @@ public void Disconnect() } ``` -**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** ```csharp using System; @@ -233,7 +244,7 @@ namespace GettingStartedApp { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("0821032395-PAXA920")) { this.myDevice = device; api.Connect(this.myDevice); @@ -244,13 +255,20 @@ namespace GettingStartedApp public void DirectConnect() { - Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); api.Connect(device); } - public bool Pay() + public OperationStartResult Pay() { return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); } public void Disconnect() @@ -291,14 +309,16 @@ namespace GettingStartedApp **1. Create buttons and labels** - Go to your user interface (usually Form1.cs[Design]) - Select View > Toolbox -- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface - Select "button1" > Right-Click > Properties - Change the attribute "Name" from "button1" to "PayButton" - Change the attribute "text" from "button1" to "Pay Now" -- Change the attribute "Name" from "button2" to "ConnectButton" -- Change the attribute "text" from "button2" to "Connect To Card reader" -- Change the attribute "Name" from "button3" to "DisconnectButton" -- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" - Select View > Toolbox > Common Controls > Label - Change the attribute "Name" from "label1" to "ConnectionLabel" - Change the attribute "text" from "label1" to "Disconnected" @@ -342,7 +362,7 @@ class MyClass : Events.Required, Events.Status ``` **2. Referencing Myclass in Form1.cs and link methods to the user interface** -Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. ```csharp using System; @@ -363,6 +383,12 @@ namespace GettingStartedApp { my.Pay(); } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } } } ``` @@ -390,6 +416,12 @@ namespace GettingStartedApp my.Pay(); } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + private void ConnectButton_Click(object sender, EventArgs e) { //my.DiscoverDevices(); @@ -534,11 +566,18 @@ namespace GettingStartedApp api.Connect(device); } - public bool Pay() + public OperationStartResult Pay() { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) return api.Sale(new BigInteger(1000), Currency.EUR); } + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + public void Disconnect() { api.Disconnect(); @@ -619,6 +658,12 @@ namespace GettingStartedApp { my.Pay(); } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } private void ConnectButton_Click(object sender, EventArgs e) { @@ -681,7 +726,8 @@ Run the program by clicking the "play" button : 1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one 2. Click "Pay Now" 3. Follow the instructions on the card reader -4. When the transaction is finished, the receipts should be displayed in the webBrowsers +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference 5. Click on "Disconnect From Card Reader" to stop the connection with the card reader ## Bluetooth (HiLite) {#WinHiLiteIntegration} @@ -1053,6 +1099,11 @@ namespace GettingStartedApp { my.Pay(); } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } } } ``` diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index e4296a6..3e2db2c 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| @@ -59,8 +59,8 @@ An object holding information about the result of a transaction. | `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| | `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| | `tid`
*String* | Terminal Identifier| -| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| | `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| | `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| @@ -122,7 +122,7 @@ An object holding information about the result of a transaction. "statusMessage": "Approved or completed successfully", "tenderType": "CREDIT", "tid": "ACQUIRER_TID", - "tipAmount": 0, + "gratuityAmount": 0, "totalAmount": 100, "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", "tsi": "0000", @@ -133,7 +133,7 @@ An object holding information about the result of a transaction. "efttimestamp": 1615374961000, "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", "requestedAmount": 100, - "tipPercentage": 0, + "gratuityPercentage": 0, "recoveredTransaction": false } ``` @@ -378,21 +378,24 @@ An enum representing different final statuses of a transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `UNKNOWN` `IN_PROGRESS` `UNKNOWN` `IN_PROGRESS` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | -| `UNDEFINED`
| Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
| The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | | `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `UNKNOWN`
| The `transactionReference` of this transaction is NOT registered in the gateway. The status of the transaction could change in the near future. | -| `IN_PROGRESS`
| The `transactionReference` of this transaction is known by the gateway. Please check the status of the transaction again as it is in the process of status change. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 2bd4f3e..c09f2df 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -10,15 +10,18 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ::: ## 4.0.0 -**Features** -We are excited to announce the launch of a new feature: [**Get Transaction Status**](windowsdevicemanagement.md#get-transaction-status). This feature allows the integrator to obtain the status of a transaction by providing a transaction reference. You can use this feature to track the progress of your payments, refunds, or transfers, and to troubleshoot any issues that may arise. To use this feature, use a [transaction reference](windowsobjects.md#operation-start-result) obtained when a new transaction has been started. This feature is available for all supported payment methods and currencies. We hope you find this feature useful and convenient. Please let us know if you have any feedback or questions. +**BREAKING CHANGE:** -## 3.4.0 +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 **Features** -We are introducing a new feature called [**Transaction Metadata**](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 3246f02..0d82746 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -60,7 +60,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -106,7 +106,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Sale Reversal @@ -152,7 +152,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Refund @@ -197,7 +197,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| @@ -245,7 +245,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Sale @@ -289,7 +289,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Refund @@ -330,7 +330,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## MoTo Reversal @@ -367,7 +367,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the gateway| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| ## Print Receipt @@ -527,7 +527,7 @@ This event is invoked when the transaction is completed, it contains the transac | Parameter | Notes | | ----------- | ----------- | -| `Boolean`| `true` if the operation was successfully sent to the payment terminal| +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md index a85d569..d8acf1a 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsobjects.md @@ -30,8 +30,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | A URL containing the customer receipt in HTML format| | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the device| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| -| `efttimestamp`
*Date* | Time of the transaction| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid| +| `efttimestamp`
*BigString* | Time of the transaction| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md index ac71adf..072a7a6 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats| | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md index f4ab24e..e3de453 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md index b2dd3a7..431e1dd 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md index 60b7127..d1e779f 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -36,8 +36,8 @@ An object holding information about the result of a transaction. | `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | | `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| | `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date* | Time of the transaction (based on the date and time of the payment terminal)| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| | `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md new file mode 100644 index 0000000..1f3a441 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md @@ -0,0 +1,392 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.UseDevice(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.UseDevice(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set parameter + +`SetParameter` Method + +Allows developers to optionally change several internal parameters of the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| +| `value` Required
*String* | New value of the parameter.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Changes the bluetooth name of card reader +api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md new file mode 100644 index 0000000..c1b88c4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void deviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032395-PAXA920")) + // Put the name of your device, it is the composition of: serial number - device model. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032395-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("0821032398-PAXA920")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void deviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void deviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void deviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void **[*deviceDiscoveryFinished*](#13)**(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void deviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.UseDevice(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +

+
+
+

Windows SDK

+
+
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md new file mode 100644 index 0000000..3e2db2c --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md @@ -0,0 +1,574 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md new file mode 100644 index 0000000..c09f2df --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md @@ -0,0 +1,83 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md new file mode 100644 index 0000000..0d82746 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowstransactions.md @@ -0,0 +1,564 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Requiredv*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment SDK during the transaction, for example 'processing'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + diff --git a/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.0.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 543a0de..2c7a2a1 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.0.0", "Windows SDK 3.4.0", "Windows SDK 3.3.0", "Windows SDK 3.2.5", From 8ca6da18f3074e5afaa02f1da8604ff43997ad5f Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 20 Jun 2023 18:27:15 +0200 Subject: [PATCH 056/115] Add: Pre-auth operations type added to REST API --- restapi/restobjects.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 92c230c..a3b4b6c 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -17,7 +17,7 @@ An enum representing different types of operations. Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` @@ -42,7 +42,10 @@ Possible Values: | `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | | `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | -| `preAuth`
*String* | Sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | Sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorizationIncrease`
*String* | It allows you to increase or decrease the initially pre-authorised amount before you capture it. | +| `preAuthorizationCapture`
*String* | Captures a pre-authorized credit card payment. | +| `preAuthorizationReversal`
*String* | Allows the merchant to reverse a previous pre-auth operation. | ## Financial Status{#financialStatus} @@ -56,8 +59,7 @@ Description of the different financial statuses: | Parameter | Notes | | ----------- | ----------- | - -| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| | `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | | `DECLINED`
| The transaction has been declined by the acquirer or issuer. | | `PROCESSED`
| The `printReceipt` operation was successful.| From b581860d550a02898945743fdbe697688737e71d Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 29 Jun 2023 11:42:12 +0200 Subject: [PATCH 057/115] Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine --- restapi/restdownloads.md | 3 ++- restapi/restendpoints.md | 12 +++++++++--- .../version-REST API 2.14.0/restdownloads.md | 3 ++- .../version-REST API 2.14.0/restendpoints.md | 12 +++++++++--- ...APIRESTCollection.postman_collection.json.zip | Bin 0 -> 8864 bytes windows/windowsobjects.md | 6 ++++-- .../version-Windows SDK 3.4.0/windowsobjects.md | 2 ++ .../version-Windows SDK 4.0.0/windowsobjects.md | 6 ++++-- 8 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 static/files/HandpointAPIRESTCollection.postman_collection.json.zip diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index c3735b1..fe7a3ba 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -7,4 +7,5 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointAPIRESTCollection.postman_collection.json.zip) + diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index 49beb4a..fae9914 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -333,7 +333,12 @@ Error example response (using invalid guid): ## /transactions/{transactionReference}/status -The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). +:::warning +This endpoint does not use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: @@ -357,6 +362,7 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | Response | Response Code | | ----------- | ----------- | | **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | | **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | **Code Example** @@ -366,8 +372,8 @@ Operation executed using CLI tool CURL: REQUEST: curl -X GET \\ -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ - "https://cloud.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) - "https://cloud.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) RESPONSE: { diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md index c3735b1..fe7a3ba 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md @@ -7,4 +7,5 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/RESTAPI.postman_collection.json.zip) \ No newline at end of file +[Download this Postman Collection](/files/HandpointAPIRESTCollection.postman_collection.json.zip) + diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md index e643506..4a2791c 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restendpoints.md @@ -333,7 +333,12 @@ Error example response (using invalid guid): ## /transactions/{transactionReference}/status -The /transactions/{transactionReference}/status endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). +:::warning +This endpoint does not use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: - AUTHORISED - Transaction was successful. @@ -356,6 +361,7 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | Response | Response Code | | ----------- | ----------- | | **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | | **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | **Code Example** @@ -365,8 +371,8 @@ Operation executed using CLI tool CURL: REQUEST: curl -X GET \\ -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ - "https://cloud.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) - "https://cloud.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) RESPONSE: { diff --git a/static/files/HandpointAPIRESTCollection.postman_collection.json.zip b/static/files/HandpointAPIRESTCollection.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..5c0de8ea29668a7739cbeda497bd4f34163abb7d GIT binary patch literal 8864 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 | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| | `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| | `issuerResponseCode`
*String* | Response code from the card issuer| | `maskedCardNumber`
*String* | Masked card number of the card used for the operation| @@ -59,8 +61,8 @@ An object holding information about the result of a transaction. | `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| | `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| | `tid`
*String* | Terminal Identifier| -| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| | `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| | `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md index d1e779f..3b7fac5 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -42,6 +42,8 @@ An object holding information about the result of a transaction. | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| | `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in future versions, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in future versions, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| | `issuerResponseCode`
*String* | Response code from the card issuer| | `maskedCardNumber`
*String* | Masked card number of the card used for the operation| diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md index 3e2db2c..a572e73 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md @@ -42,6 +42,8 @@ An object holding information about the result of a transaction. | `errorMessage`
*String* | Detailed reason for the transaction error| | `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| | `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| | `issuerResponseCode`
*String* | Response code from the card issuer| | `maskedCardNumber`
*String* | Masked card number of the card used for the operation| @@ -59,8 +61,8 @@ An object holding information about the result of a transaction. | `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| | `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| | `tid`
*String* | Terminal Identifier| -| `gratuityAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `gratuityPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| | `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| | `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| | `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| From 4da3a2886c2e29942857440a6d641a8db046ab07 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 4 Jul 2023 17:54:14 +0200 Subject: [PATCH 058/115] Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK --- android/androiddevicemanagement.md | 2 +- android/androidobjects.md | 2 +- .../version-Android SDK 7.1002.0/androiddevicemanagement.md | 2 +- .../version-Android SDK 7.1002.0/androidobjects.md | 2 +- javascript/javascriptintroduction.md | 4 ++-- .../version-JavaScript SDK 7.0.0/javascriptintroduction.md | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index d9c1d01..f8453d9 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -254,7 +254,7 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL| **Code example** diff --git a/android/androidobjects.md b/android/androidobjects.md index 307db54..c1aede7 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -1020,7 +1020,7 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` ## Tender Type{#36} diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md index 1d6f08f..d0a008a 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md @@ -254,7 +254,7 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO.| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md index 307db54..c1aede7 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -1020,7 +1020,7 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` ## Tender Type{#36} diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index afb4496..8a4b1f6 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md index afb4496..8a4b1f6 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

From d6e00b4c729844162c5b3122deb4eda84a146eca Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 6 Jul 2023 17:46:11 +0200 Subject: [PATCH 059/115] Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK --- docusaurus.config.js | 2 +- javascript/javascriptquickintegration.md | 2 +- javascript/javascriptreleasenotes.md | 2 +- javascript/javascriptterminalmanagement.md | 2 +- .../javascriptquickintegration.md | 2 +- .../javascriptreleasenotes.md | 2 +- .../javascriptterminalmanagement.md | 2 +- windows/windowsintegrationguide.md | 28 +++++++++---------- .../windowsintegrationguide.md | 28 +++++++++---------- .../windowsintegrationguide.md | 26 ++++++++--------- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 86ff891..69d05eb 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,7 +229,7 @@ module.exports = { '@docusaurus/plugin-content-docs', { id: 'javascript', - includeCurrentVersion: true, // dev: Change to true + includeCurrentVersion: false, // dev: Change to true path: 'javascript', routeBasePath: 'javascript', sidebarPath: require.resolve('./sidebarsIos.js'), diff --git a/javascript/javascriptquickintegration.md b/javascript/javascriptquickintegration.md index 13a7870..f5c935d 100644 --- a/javascript/javascriptquickintegration.md +++ b/javascript/javascriptquickintegration.md @@ -88,7 +88,7 @@ The following example shows how you can integrate your web application with the // Retrieve transaction status hp.getTransactionStatus(result.transactionReference).then( transactionResult => { - console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + console.log('Transaction Result (from getTransactionStatus) -> ' + JSON.stringify(transactionResult)) } ).catch( errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 98c0f37..a5fc7d3 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -12,7 +12,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 **BREAKING CHANGE:** -We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: diff --git a/javascript/javascriptterminalmanagement.md b/javascript/javascriptterminalmanagement.md index e945802..9a7c809 100644 --- a/javascript/javascriptterminalmanagement.md +++ b/javascript/javascriptterminalmanagement.md @@ -259,4 +259,4 @@ Handpoint.getTransactionStatus(transactionReference).then( | Parameter | Notes | | ----------- | ----------- | -| **Transaction Status**| The status of the requested transaction.| \ No newline at end of file +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md index 13a7870..f5c935d 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptquickintegration.md @@ -88,7 +88,7 @@ The following example shows how you can integrate your web application with the // Retrieve transaction status hp.getTransactionStatus(result.transactionReference).then( transactionResult => { - console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + console.log('Transaction Result (from getTransactionStatus) -> ' + JSON.stringify(transactionResult)) } ).catch( errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md index 98c0f37..a5fc7d3 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md @@ -12,7 +12,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.0.0 **BREAKING CHANGE:** -We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#transaction-reference) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md index 026fb77..102231d 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptterminalmanagement.md @@ -258,4 +258,4 @@ Handpoint.getTransactionStatus(transactionReference).then( | Parameter | Notes | | ----------- | ----------- | -| **Transaction Status**| The status of the requested transaction.| \ No newline at end of file +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index c1b88c4..828cf85 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -140,13 +140,13 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032395-PAXA920")) + if (device.Name.Equals("CloudDevice")) // Put the name of your device, it is the composition of: serial number - device model. // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 { @@ -238,13 +238,13 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032395-PAXA920")) + if (device.Name.Equals("CloudDevice")) { this.myDevice = device; api.Connect(this.myDevice); @@ -602,13 +602,13 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032398-PAXA920")) + if (device.Name.Equals("CloudDevice")) { this.myDevice = device; api.Connect(this.myDevice); @@ -830,7 +830,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -880,7 +880,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -961,7 +961,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1301,7 +1301,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1543,7 +1543,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1629,7 +1629,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1880,7 +1880,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md index dabc7c4..c9747f4 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -140,13 +140,13 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("CloudDevice")) // Put the name of your device, it is the composition of: serial number - device model. // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 { @@ -227,13 +227,13 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) + if (device.Name.Equals("CloudDevice")) { this.myDevice = device; api.Connect(this.myDevice); @@ -563,13 +563,13 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032398-PAXA920")) + if (device.Name.Equals("CloudDevice")) { this.myDevice = device; api.Connect(this.myDevice); @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -834,7 +834,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -915,7 +915,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1492,7 +1492,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1578,7 +1578,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1829,7 +1829,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md index c1b88c4..29ac0c8 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -140,13 +140,13 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032395-PAXA920")) + if (device.Name.Equals("CloudDevice")) // Put the name of your device, it is the composition of: serial number - device model. // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 { @@ -238,7 +238,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -602,13 +602,13 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("0821032398-PAXA920")) + if (device.Name.Equals("CloudDevice")) { this.myDevice = device; api.Connect(this.myDevice); @@ -830,7 +830,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -880,7 +880,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -961,7 +961,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1301,7 +1301,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1543,7 +1543,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1629,7 +1629,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1880,7 +1880,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC From 5b0bcf6b71bef33b5d7760c5ee29554be474e1e1 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 7 Jul 2023 12:02:46 +0200 Subject: [PATCH 060/115] Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide --- windows/windowsintegrationguide.md | 4 +-- .../windowsintegrationguide.md | 28 +++++++++---------- .../windowsintegrationguide.md | 4 +-- .../windowsintegrationguide.md | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index 828cf85..ec75751 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -147,8 +147,8 @@ public void DeviceDiscoveryFinished(List devices) if (device.Name != null) { if (device.Name.Equals("CloudDevice")) - // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + // Put the name of your device + { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md index 3b3c855..e5739f8 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md @@ -94,7 +94,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // here you get a list of payment terminals associated with the api key. } @@ -140,15 +140,15 @@ public void DiscoverDevices() api.SearchDevices(ConnectionMethod.CLOUD); } -public void deviceDiscoveryFinished(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { if (device.Name != null) { - if (device.Name.Equals("9822032398-PAXA920")) - // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + if (device.Name.Equals("CloudDevice")) + // Put the name of your device + { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too @@ -227,7 +227,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.CLOUD); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -563,7 +563,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -784,7 +784,7 @@ namespace GettingStartedApp api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { // Here you get a list of Bluetooth payment terminals paired with your computer } @@ -834,7 +834,7 @@ public void DiscoverDevices() // You can also search for USB and Serial as a connection method } -public void **[*deviceDiscoveryFinished*](#13)**(List devices) +public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -915,7 +915,7 @@ namespace GettingStartedApp api.SearchDevices(ConnectionMethod.BLUETOOTH); } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1250,7 +1250,7 @@ namespace GettingStartedApp Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); } - public void deviceDiscoveryFinished(List devices) + public void DeviceDiscoveryFinished(List devices) { foreach (Device device in devices) { @@ -1492,7 +1492,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen // It prevents other people to connect to your card reader } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //here you get a list of Bluetooth payment terminals paired with your PC @@ -1578,7 +1578,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC @@ -1829,7 +1829,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : // It prevents other people to connect to your card reader. } - public void **[*deviceDiscoveryFinished*](#13)**(List devices) + public void DeviceDiscoveryFinished(List devices) { // Only needed when using a payment terminal //Here you get a list of Bluetooth payment terminals paired with your PC diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md index c9747f4..70eecfe 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md @@ -147,8 +147,8 @@ public void DeviceDiscoveryFinished(List devices) if (device.Name != null) { if (device.Name.Equals("CloudDevice")) - // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 + // Put the name of your device + { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md index 29ac0c8..6289f98 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md @@ -147,8 +147,8 @@ public void DeviceDiscoveryFinished(List devices) if (device.Name != null) { if (device.Name.Equals("CloudDevice")) - // Put the name of your device, it is the composition of: serial number - device model. - // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + // Put the name of your device + { this.myDevice = device; //We'll remember the device for this session, it is nice if you would do that too From 079454522e315929482ffe13a411bed6be1386b3 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 12 Jul 2023 13:52:44 +0200 Subject: [PATCH 061/115] Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --- android/androidobjects.md | 2 +- .../version-Android SDK 7.1001.0/androidobjects.md | 2 +- .../version-Android SDK 7.1002.0/androidobjects.md | 2 +- windows/windowsobjects.md | 2 +- .../version-Windows SDK 3.4.0/windowsobjects.md | 2 +- .../version-Windows SDK 4.0.0/windowsobjects.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index c1aede7..add8df3 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -719,7 +719,7 @@ An enum representing different types of scenario. **Possible values** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## PAX A80 Keys{#28} diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md index 5bfa2ff..9faec6b 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md @@ -715,7 +715,7 @@ An enum representing different types of scenario. **Possible values** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## PAX A80 Keys{#28} diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md index c1aede7..add8df3 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -719,7 +719,7 @@ An enum representing different types of scenario. **Possible values** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## PAX A80 Keys{#28} diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index dad5988..c5ee083 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -472,7 +472,7 @@ An enum representing different types of payment scenarios. ** Possible values ** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## Status diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md index 3b7fac5..82f9be3 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -467,7 +467,7 @@ An enum representing different types of payment scenarios. ** Possible values ** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## Status diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md index a572e73..844878e 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md @@ -472,7 +472,7 @@ An enum representing different types of payment scenarios. ** Possible values ** -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` ## Status From 52c1a16239aa05ae6c7fb01b369828e2027b0a1d Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 25 Aug 2023 13:09:47 +0200 Subject: [PATCH 062/115] Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Add: Estonian as locale * Add: Preauth for JavaScript SDK * Add: Pre-Auth release notes, Win and JS docs, Postman collection * Update androidreleasenotes.md * Update androidtransactions.md * Update androidtransactions.md * Update javascriptreleasenotes.md * Update androidreleasenotes.md * Update javascriptreleasenotes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowstransactions.md --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> --- android/androiddevicemanagement.md | 3 +- android/androidobjects.md | 3 +- android/androidreleasenotes.md | 10 +- android/androidtransactions.md | 72 ++++- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 3 +- .../androidreleasenotes.md | 2 + javascript/javascriptreleasenotes.md | 11 + javascript/javascripttransactiontypes.md | 192 ++++++++++++++ .../javascripttransactiontypes.md | 26 ++ restapi/restdownloads.md | 5 +- restapi/restreleasenotes.md | 14 + static/files/Handpoint_APIREST_Aug23.json.zip | Bin 0 -> 8970 bytes windows/windowsreleasenotes.md | 11 + windows/windowstransactions.md | 248 ++++++++++++++++++ 15 files changed, 581 insertions(+), 21 deletions(-) create mode 100644 static/files/Handpoint_APIREST_Aug23.json.zip diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index f8453d9..5fb2f97 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -254,7 +254,8 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + **Code example** diff --git a/android/androidobjects.md b/android/androidobjects.md index add8df3..4c70c28 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -1020,7 +1020,8 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + ## Tender Type{#36} diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 9fb2597..0fe2b69 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -14,7 +14,13 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1003.0 **Features**: -We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). The pre-authorization feature refers to a process where a certain amount of funds is temporarily reserved or held from a customer's account before the actual payment transaction takes place. During the pre-authorization period the funds are reserved but not yet transferred from the cardholder's account to the merchant. +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increase)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be partially or fully released ([Pre-Auth Reversal](androidtransactions.md#pre-auth-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. ## 7.1002.0 @@ -24,6 +30,8 @@ We are introducing a new feature called [Get Transaction Status](androiddevicema - Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. +Added Estonian language 🇪🇪 + ## 7.1001.0 **Features**: diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 26a1e60..9e3058a 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -592,6 +592,7 @@ Invoked when the terminal finishes processing the transaction. `preAuthorization` A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. **Parameters** @@ -606,6 +607,9 @@ A pre-auth initiates a pre-authorization operation to the card reader. In it's s ```java //Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); preauthOptions.setCustomerReference("CustomerReference"); @@ -636,17 +640,17 @@ Invoked when the terminal finishes processing the transaction. `preAuthorizationIncrease` -A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `tipAmount`
*BigInteger* | Currency of the charge| -| `originalTransactionID` Required
*String* | Currency of the charge| +| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| | `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| **Code example** @@ -656,7 +660,7 @@ A pre-auth initiates a pre-authorization operation to the card reader. In it's s Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); -api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP, preauthOptions); +api.preAuthorizationIncrease(new BigInteger("1000"),Currency.GBP,new BigInteger("100"),"00000000-0000-0000-0000-000000000000", preauthOptions); ``` **Events invoked** @@ -683,7 +687,47 @@ Invoked when the terminal finishes processing the transaction. `preAuthorizationCapture` -A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 30 days | 20% | +| 5814 | Fast Food Restaurants | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + **Parameters** @@ -692,8 +736,8 @@ A pre-auth initiates a pre-authorization operation to the card reader. In it's s | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `tipAmount`
*BigInteger* | Currency of the charge| -| `originalTransactionID` Required
*String* | Currency of the charge| +| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| | `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| **Code example** @@ -703,7 +747,7 @@ A pre-auth initiates a pre-authorization operation to the card reader. In it's s Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); -api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP, preauthOptions); +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,new BigInteger("100"),"00000000-0000-0000-0000-000000000000", preauthOptions); ``` **Events invoked** @@ -728,15 +772,16 @@ Invoked when the terminal finishes processing the transaction. `preAuthorizationReversal` -A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `originalTransactionID` Required
*String* |Transaction id of the original transaction| -| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| **Code example** @@ -747,6 +792,7 @@ api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); +//Initiate a pre-auth reversal with options api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); ``` @@ -766,4 +812,4 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| \ No newline at end of file +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md index 53f1b42..d40ca88 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md @@ -254,7 +254,7 @@ Sets the SDK Locale (language). It is used to set the SDK language as well as th | Parameter | Notes | | ----------- | ----------- | -| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL| +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md index 55bc873..f23ec56 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -1021,7 +1021,8 @@ An enum of the SDK supported languages. **Possible values** -`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + ## Tender Type{#36} diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md index 1fe0760..1c8b3d4 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md @@ -19,6 +19,8 @@ We are introducing a new feature called [Get Transaction Status](androiddevicema - Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. +Added Estonian language 🇪🇪 + ## 7.1001.0 **Features**: diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index a5fc7d3..ec96312 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -9,6 +9,17 @@ id: javascriptreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increase)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be partially or fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-auth-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + ## 7.0.0 **BREAKING CHANGE:** diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index cff61b8..9b044ca 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -409,6 +409,33 @@ let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000 | *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + ## Tokenize Card{#11} @@ -472,3 +499,168 @@ Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); | **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase + +`preAuthorizationIncrease` + +This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `tipAmount`
*BigInteger* | Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','100','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 30 days | 20% | +| 5814 | Fast Food Restaurants | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','100','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md index cff61b8..b935b89 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascripttransactiontypes.md @@ -409,6 +409,32 @@ let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000 | *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + ## Tokenize Card{#11} diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index fe7a3ba..f9d3c63 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,7 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). - -[Download this Postman Collection](/files/HandpointAPIRESTCollection.postman_collection.json.zip) +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +[Download this Postman Collection](/files/Handpoint_APIREST_Aug23.json.zip) diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 9880b1b..dd7c888 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,20 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called Pre-Authorization. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased, for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + + In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + ## 2.14.0 **Features:** diff --git a/static/files/Handpoint_APIREST_Aug23.json.zip b/static/files/Handpoint_APIREST_Aug23.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..fdb441fbf09a781ca290449a0956f7ecd1b836ac GIT binary patch literal 8970 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
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase + +`preAuthorizationIncrease` + +This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 30 days | 20% | +| 5814 | Fast Food Restaurants | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, new BigInteger("100"),"00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, new BigInteger("100"),"00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| From 5a1d1c4f0d41c57d3b6d1f1acd037de62b60200c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicente=20Pav=C3=B3n?= <30615276+vicentepdj@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:35:03 +0200 Subject: [PATCH 063/115] chore: Increase timeout GHA (#81) chore: Increase Timeout GHA wf deploy --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 23f8266..c21a190 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,7 +10,7 @@ jobs: test-deploy: if: github.event_name != 'push' runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v3 @@ -24,7 +24,7 @@ jobs: deploy: if: github.event_name != 'pull_request' runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v3 From 46ba27d0c6723ade4567d377ff191e5ea8ed9425 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 29 Aug 2023 16:32:50 +0200 Subject: [PATCH 064/115] Feature tokenize and modify operation (#84) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md --------- Co-authored-by: Antoine --- android/androideventlisteners.md | 31 ++++++++++++++- android/androidobjects.md | 31 +++++++++++++++ android/androidtransactions.md | 68 ++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/android/androideventlisteners.md b/android/androideventlisteners.md index d7c103c..dd79145 100644 --- a/android/androideventlisteners.md +++ b/android/androideventlisteners.md @@ -149,6 +149,33 @@ public final class EventHandler implements Events.CardBrandDisplay { this.api.registerEventsDelegate(eventHandlerInstance); ``` +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + ## Connection status changed{#connectionStatusChanged} `Events.ConnectionStatusChanged` Interface @@ -179,6 +206,8 @@ public final class EventHandler implements Events.ConnectionStatusChanged { this.api.registerEventsDelegate(eventHandlerInstance); ``` + + ## Current transaction status{#14} `Events.CurrentTransactionStatus` Interface @@ -280,7 +309,7 @@ Implement this interface to receive an event when a transaction is complete. **Methods** -`dendOfTransaction( TransactionResult result , Device device );` +`endOfTransaction( TransactionResult result , Device device );` | Parameter | Notes | | ----------- | ----------- | diff --git a/android/androidobjects.md b/android/androidobjects.md index 4c70c28..470878c 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -243,6 +243,22 @@ A string representing different card brands. `MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + ## Connection Method{#20} `ConnectionMethod` Enum @@ -656,6 +672,21 @@ options.setChannel(MoToChannel.MO); options.setChannel(MoToChannel.TO); ``` +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + ## Operation Start Result {#OperationStartResult} diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 9e3058a..dd4f90c 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -545,7 +545,75 @@ Invoked when the terminal finishes processing the transaction. | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +## Tokenize And Modify +`tokenizedOperation` +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java + +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + ## Card PAN{#13} `cardPan` From e746cb3df7aae60f13c29772d55bf9eb92e2a01c Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 30 Aug 2023 16:11:48 +0200 Subject: [PATCH 065/115] Fix: Tokenize and modify code sample (#85) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md * Fix: TokenizeAndModify code sample --------- Co-authored-by: Antoine --- android/androidtransactions.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/android/androidtransactions.md b/android/androidtransactions.md index dd4f90c..11d50bf 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -560,7 +560,6 @@ A tokenize and modify operation allows you to start a financial operation for an | `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| ```java - //Tokenize a card and modifies the amount of a sale operation. //Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. //Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. @@ -573,6 +572,20 @@ options.setMetadata(metadata); api.tokenizedOperation(Currency.GBP,options); +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// //Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. //This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. From badf5d8daa9b45cd87fcf2db0e109e4657f0d723 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 18 Sep 2023 11:12:41 +0200 Subject: [PATCH 066/115] Add: MoTo PreAuth for Android, JS SDK and REST API (#86) --- android/androidtransactions.md | 45 + javascript/javascripttransactiontypes.md | 38 + restapi/restdownloads.md | 4 +- restapi/restobjects.md | 1 + static/files/Handpoint_API_REST_Sept2023.json | 773 ++++++++++++++++++ .../Handpoint_API_REST_Sept2023.json.zip | Bin 0 -> 9010 bytes 6 files changed, 859 insertions(+), 2 deletions(-) create mode 100644 static/files/Handpoint_API_REST_Sept2023.json create mode 100644 static/files/Handpoint_API_REST_Sept2023.json.zip diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 11d50bf..d74879b 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -411,6 +411,50 @@ Invoked when the terminal finishes processing the transaction. | *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + ## Signature result `signatureResult` @@ -454,6 +498,7 @@ Invoked when the terminal finishes processing the transaction. + ## Tip Adjustment `TipAdjustment` diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 9b044ca..7d62fd4 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -409,6 +409,44 @@ let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000 | *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + ## Tip Adjustment `TipAdjustment` diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index f9d3c63..1ff98d8 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/Handpoint_APIREST_Aug23.json.zip) +[Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index fc62c81..9c21fdb 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -42,6 +42,7 @@ Possible Values: | `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | | `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | | `preAuthorization`
*String* | Sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | | `preAuthorizationIncrease`
*String* | It allows you to increase or decrease the initially pre-authorised amount before you capture it. | | `preAuthorizationCapture`
*String* | Captures a pre-authorized credit card payment. | diff --git a/static/files/Handpoint_API_REST_Sept2023.json b/static/files/Handpoint_API_REST_Sept2023.json new file mode 100644 index 0000000..2b36bcd --- /dev/null +++ b/static/files/Handpoint_API_REST_Sept2023.json @@ -0,0 +1,773 @@ +{ + "info": { + "_postman_id": "5ef46b32-777a-4f6d-9ad2-6137814d0eb5", + "name": "Handpoint API REST Delivery", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "3069504" + }, + "item": [ + { + "name": "Initialize", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API KEY" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "https://cloud.handpoint.com/initialize", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "initialize" + ] + } + }, + "response": [] + }, + { + "name": "Ping Device", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your Api Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"pingDevice\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Your callbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Sale", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"sale\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callbackUrl\",\n \"token\":\"123456789\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "MotoSale", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"motoSale\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Moto PreAuth", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"moToPreAuthorization\",\n \"amount\":\"1000\",\n \"currency\":\"USD\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callbackUrl\",\n \"token\":\"123456789\"\n \n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Sale and Tokenize", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your Api Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"saleAndTokenizeCard\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Your callbackUrl\",\n \"token\":\"123456789\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Sale Reversal", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Introduce your API KEY" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"saleReversal\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Introduce your device Serial Number\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Introduce your callbackUrl\",\n \"token\":\"123456789\",\n \"originalTransactionId\":\"Introduce original transactionID\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Sale Partial Approval (US feature)", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API KEY" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"sale\",\n \"amount\":\"3757\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"YourDeviceSN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"YourCallbackUrl\",\n \"token\":\"123456789\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Refund (NOT Linked Refund)", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API KEY", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"refund\",\n \"amount\":\"1000\",\n \"currency\":\"USD\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"yourDeviceSN\",\n \"callbackUrl\":\"yourCallbackURL\",\n \"token\":\"1234556\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Refund (Linked Refund)", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API KEY", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"refund\",\n \"amount\":\"1000\",\n \"currency\":\"USD\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"callbackUrl\":\"yourcallbackURL\",\n \"token\":\"1234556\",\n \"originalTransactionId\": \"Introduce original transactionID\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Refund Reversal", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your Api Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"refundReversal\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Your callbackUrl\",\n \"token\":\"123456789\",\n \"originalTransactionId\":\"your original trx ID\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Tokenize Card", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API KEY" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"tokenizeCard\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Your callbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Update", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"update\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"your device serial_number\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"Your callbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "GetTransactionResult", + "request": { + "method": "GET", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key", + "type": "text" + } + ], + "url": { + "raw": "https://cloud.handpoint.com/transaction-result/0812345678-11223344556677", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transaction-result", + "0812345678-11223344556677" + ] + } + }, + "response": [] + }, + { + "name": "StopCurrentTransaction", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"stopCurrentTransaction\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"yourDeviceSN\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "Tip-Adjustment", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCloud", + "value": "Your API Key" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"amount\": 1.23\n}" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions/your-GUID-here/tip-adjustment", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions", + "your-GUID-here", + "tip-adjustment" + ] + } + }, + "response": [] + }, + { + "name": "printReceipt Bitmap", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "yourAPIKey" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"printReceipt\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"yourDeviceSN\",\n \"customerReference\": \"yourCustomerReference\",\n \"receipt\":\"\",\n \"callbackUrl\":\"yourCallbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "printReceipt Custom Receipt", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "yourAPIKey" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"printReceipt\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"yourCustomerReference\",\n \"receipt\":\"\\n\\n\\n
\\n \\n
\\n

Test Receipt

\\n
\\n
\\n

London

\\n
\\n
\\n
\\n \\n 16:45\\n
\\n
\\n
\\n
\\n

AUTORIZADA:

\\n
\\n
\\n

\\n
\\n
\\n

VENTA

\\n
\\n
\\n \\n USD 110.00\\n
\\n
\\n
\\n \\n ****3344\\n
\\n
\\n \\n *****9951\\n
\\n
\\n \\n **** **** **** 2907\\n
\\n
\\n \\n Chip\\n
\\n
\\n \\n VERIFICADO POR DISPOSITIVO\\n
\\n
\\n \\n 123456\\n
\\n
\\n \\n DÉBITO\\n
\\n
\\n
\\n

GUID

\\n
\\n
\\n

46c50750-56cf-11ed-bae9-335a2b81aa23

\\n
\\n
\\n
\\n

** COPIA COMPRADOR **

\\n
\\n
\\n
\\n

EMV Details

\\n
\\n
\\n \\n A0000000031010\\n
\\n
\\n \\n 0080008000\\n
\\n
\\n \\n 06150A03A4A802\\n
\\n
\\n \\n E800\\n
\\n
\\n \\n 0000\\n
\\n
\\n
\\n
\\n
\\n
\\n\\n \",\n \"callbackUrl\":\"yourCallbackUrl\",\n \"token\":\"123456789\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "GetTransactionStatus", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "Your API Key" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "https://transactions.handpoint.com/transactions/00000000-0000-0000-0000-000000000000/status/", + "protocol": "https", + "host": [ + "transactions", + "handpoint", + "com" + ], + "path": [ + "transactions", + "00000000-0000-0000-0000-000000000000", + "status", + "" + ] + } + }, + "response": [] + }, + { + "name": "PreAuth", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"preAuthorization\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callback URL\",\n \"token\":\"123456789\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions/5b252fa0-903a-11ed-a4db-1d97852dd668/tip-adjustment", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions", + "5b252fa0-903a-11ed-a4db-1d97852dd668", + "tip-adjustment" + ] + } + }, + "response": [] + }, + { + "name": "PreAuth Increase", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"preAuthorizationIncrease\",\n \"amount\":\"1000\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"0821599465\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callback URL\",\n \"token\":\"12343264757\",\n \"originalTransactionId\":\"00000000-0000-0000-0000-000000000000\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions/", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions", + "" + ] + } + }, + "response": [] + }, + { + "name": "PreAuth Capture", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"preAuthorizationCapture\",\n \"amount\":\"100\",\n \"currency\":\"EUR\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callback URL\",\n \"token\":\"12343264757\",\n \"originalTransactionId\":\"00000000-0000-0000-0000-000000000000\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + }, + { + "name": "PreAuth Reversal", + "request": { + "method": "POST", + "header": [ + { + "key": "ApiKeyCLoud", + "value": "" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"operation\":\"preAuthorizationReversal\",\n \"terminal_type\":\"PAXA920\",\n \"serial_number\":\"Your device SN\",\n \"customerReference\": \"op15248\",\n \"callbackUrl\":\"your callback URL\",\n \"token\":\"12343264757\",\n \"originalTransactionId\":\"00000000-0000-0000-0000-000000000000\",\n \"transactionReference\": \"00000000-0000-0000-0000-000000000000\"\n }" + }, + "url": { + "raw": "https://cloud.handpoint.com/transactions", + "protocol": "https", + "host": [ + "cloud", + "handpoint", + "com" + ], + "path": [ + "transactions" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/static/files/Handpoint_API_REST_Sept2023.json.zip b/static/files/Handpoint_API_REST_Sept2023.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..3ba49943e3dcdb8b6022119ecd6051ed5896b10e GIT binary patch literal 9010 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 Date: Mon, 18 Sep 2023 13:05:27 +0200 Subject: [PATCH 067/115] CICD-55 (#87) chore: use new txn feed doc address --- restapi/restobjects.md | 2 +- restapi_versioned_docs/version-REST API 2.10.0/restobjects.md | 2 +- restapi_versioned_docs/version-REST API 2.12.0/restobjects.md | 2 +- restapi_versioned_docs/version-REST API 2.13.0/restobjects.md | 2 +- restapi_versioned_docs/version-REST API 2.14.0/restobjects.md | 2 +- restapi_versioned_docs/version-REST API 2.7.1/restobjects.md | 2 +- src/pages/index.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 9c21fdb..d9dcdd2 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -232,7 +232,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index 18a0706..e376444 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -213,7 +213,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md index 8665bc2..6248716 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -213,7 +213,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md index c96fff0..fcb6ca3 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md @@ -221,7 +221,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md index 5168406..df0a9d5 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md @@ -226,7 +226,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md index a397551..28c1ae7 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md @@ -214,7 +214,7 @@ An object to store information about the request sent to the payment terminal. | `terminal_type` Required
*String* | Type of terminal. | | `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | | `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | -| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://handpoint.com/docs/txnfeedapi/#api-Transactions-getTxnByCustomerReference. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | diff --git a/src/pages/index.js b/src/pages/index.js index 0c9756c..bae2a87 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -92,7 +92,7 @@ function Options() {
From 394c7cc08d0bec235a5781db750769e784f158cf Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 25 Sep 2023 17:01:06 +0200 Subject: [PATCH 068/115] DOCWEB-80 (#88) fix: remove tipAmount for preAuth operations --- javascript/javascripttransactiontypes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 7d62fd4..9e41526 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -579,7 +579,6 @@ This operation allows the merchant to increase the amount of a previously perfor | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
*Currency* | Currency of the charge| -| `tipAmount`
*BigInteger* | Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| | `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| | `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| @@ -588,7 +587,7 @@ This operation allows the merchant to increase the amount of a previously perfor ```javascript // Perform the PreAuth Increase operation -let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','100','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { console.log('Transaction status received -> '+ stat.message) }); ``` @@ -660,7 +659,7 @@ A pre-authorized transaction can be captured to actually debit the cardholder's ```javascript // Perform the PreAuth Capture operation -let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','100','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { console.log('Transaction status received -> '+ stat.message) }); ``` From 31261237119e7cac933e8b58c5d31ecc40c2b28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Tue, 3 Oct 2023 10:22:42 +0200 Subject: [PATCH 069/115] SDK-3434 (#89) * fix: remove tipAmount parameter from PreAuthorizationCapture * chore: remove typo --- windows/windowstransactions.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 54fe6b1..d3fa8b8 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -453,7 +453,6 @@ Note: This functionality is only available for the restaurant industry in the Un | Parameter | Notes | | ----------- | ----------- | -| `tipAmount` Required
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). | | `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | @@ -721,21 +720,20 @@ A pre-authorized transaction can be captured to actually debit the cardholder's | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| -| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| **Code example** ```csharp // Basic -this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, new BigInteger("100"),"00000000-0000-0000-0000-000000000000"); +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000"); // With options Dictionary map = new Dictionary(); map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); map.Add(XmlTag.Metadata1.Tag(), "Data 1"); -this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, new BigInteger("100"),"00000000-0000-0000-0000-000000000000", map); +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); ``` #### Events invoked From 2c7352301f797fe97249b4820f00e7c5d37df4f0 Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 5 Oct 2023 18:08:16 +0200 Subject: [PATCH 070/115] fix: include moToPreAuthorization in operation types (possible values) (#90) --- restapi/restobjects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index d9dcdd2..2b7cdf2 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -17,7 +17,7 @@ An enum representing different types of operations. Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` From 4a10f2cae1a3c1a919a79f43bf28edd0811701b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Fri, 6 Oct 2023 13:18:35 +0200 Subject: [PATCH 071/115] REST-API doc fix (#91) chore: add preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal to the operations that require the originalTransactionId parameter --- restapi/restobjects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 2b7cdf2..3efb33c 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -235,7 +235,7 @@ An object to store information about the request sent to the payment terminal. | `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | | `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | | `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | -| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction. **REQUIRED** for operations: refundReversal, saleReversal and LINKED refunds. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | | `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | | `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | | `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | From c0be0f888b7bb131f44389c1b53a2c98c4019335 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 17 Oct 2023 16:21:04 +0200 Subject: [PATCH 072/115] Fixes PreAuth WinSDK (#92) Add: FAILED to GTS finStatus for WinSDK - Add: FAILED to GTS finStatus for WinSDK - Fix: Connect method integration guide for WinSDK - Fix: TipConfiguration code example for REST API --- restapi/restobjects.md | 25 ++++--- .../version-REST API 2.10.0/restobjects.md | 25 ++++--- .../version-REST API 2.12.0/restobjects.md | 25 ++++--- .../version-REST API 2.13.0/restobjects.md | 25 ++++--- .../version-REST API 2.14.0/restobjects.md | 25 ++++--- .../version-REST API 2.6.0/restobjects.md | 25 ++++--- .../version-REST API 2.7.1/restobjects.md | 25 ++++--- windows/windowsdevicemanagement.md | 5 +- windows/windowsintegrationguide.md | 10 +-- windows/windowsobjects.md | 5 +- windows/windowstransactions.md | 69 +++++++++++++++---- .../windowsdevicemanagement.md | 4 +- .../windowsintegrationguide.md | 10 +-- .../windowsdevicemanagement.md | 4 +- .../windowsintegrationguide.md | 10 +-- .../windowsdevicemanagement.md | 4 +- .../windowsintegrationguide.md | 10 +-- .../windowsdevicemanagement.md | 4 +- .../windowsintegrationguide.md | 10 +-- .../windowsobjects.md | 2 +- .../windowsdevicemanagement.md | 4 +- .../windowsintegrationguide.md | 10 +-- .../windowsobjects.md | 2 +- .../windowsdevicemanagement.md | 5 +- .../windowsintegrationguide.md | 10 +-- .../windowsobjects.md | 2 +- 26 files changed, 226 insertions(+), 129 deletions(-) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 3efb33c..2ef6816 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -620,7 +620,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -631,14 +631,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md index e376444..d6bb448 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restobjects.md @@ -583,7 +583,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -594,14 +594,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md index 6248716..82197b8 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restobjects.md @@ -583,7 +583,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -594,14 +594,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md index fcb6ca3..fae8f7b 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restobjects.md @@ -606,7 +606,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -617,14 +617,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md index df0a9d5..ab888ab 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restobjects.md @@ -614,7 +614,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -625,14 +625,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md index f5d4857..6f38e53 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restobjects.md @@ -563,7 +563,7 @@ Properties | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -574,14 +574,21 @@ Properties ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md index 28c1ae7..8a21c54 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restobjects.md @@ -580,7 +580,7 @@ An enum containing information about the status of a transaction. | Property | Description | | ----------- | ----------- | -| `baseAmount`
*Biginteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | | `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | | `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | | `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | @@ -591,14 +591,21 @@ An enum containing information about the status of a transaction. ````json { - "baseAmount": "2000", - "headerName": "", - "tipPercentages": [5,10,15,20,25], - "enterAmountEnabled": true, - "skipEnabled": false, - "footer": "Thank you!!! ;)" -} - + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } ```` ## Tender Type{#tenderType} diff --git a/windows/windowsdevicemanagement.md b/windows/windowsdevicemanagement.md index b78893d..f210b9e 100644 --- a/windows/windowsdevicemanagement.md +++ b/windows/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked @@ -372,6 +372,7 @@ The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a res - UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. - IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. - REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. **Parameters** diff --git a/windows/windowsintegrationguide.md b/windows/windowsintegrationguide.md index 0ace982..1ff930d 100644 --- a/windows/windowsintegrationguide.md +++ b/windows/windowsintegrationguide.md @@ -1437,13 +1437,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1576,7 +1576,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1640,7 +1640,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1891,7 +1891,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index 4d46f17..f8ca59d 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -380,7 +380,7 @@ An enum representing different final statuses of a transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` Description of the different financial statuses: @@ -395,6 +395,7 @@ An enum representing different final statuses of a transaction. | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. @@ -415,7 +416,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| | `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index d3fa8b8..32d6295 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -135,7 +135,7 @@ api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-0000 **[*currentTransactionStatus*](windowsevents.md#4)** -Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' **** **[*signatureRequired*](windowsevents.md#5)** @@ -277,7 +277,7 @@ this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment SDK during the transaction, for example 'processing'. +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*endOfTransaction*](windowsevents.md#6)** @@ -303,7 +303,7 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | Parameter | Notes | | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| -| `currency` Requiredv*Currency* | Currency of the transaction.| +| `currency` Required*Currency* | Currency of the transaction.| | `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| | `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| @@ -318,7 +318,7 @@ this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-000 **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment SDK during the transaction, for example 'processing'. +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*endOfTransaction*](windowsevents.md#6)** @@ -355,7 +355,52 @@ this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment SDK during the transaction, for example 'processing'. +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +|`currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*endOfTransaction*](windowsevents.md#6)** @@ -426,7 +471,7 @@ public void SignatureRequired(SignatureRequest signatureRequest, Device device) **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*endOfTransaction*](windowsevents.md#6)** @@ -509,7 +554,7 @@ api.TokenizeCard(); **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*signatureRequired*](windowsevents.md#5)** @@ -547,7 +592,7 @@ this.Hapi.StopCurrentTransaction(); **[*currentTransactionStatus*](windowsevents.md#4)** -This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*endOfTransaction*](windowsevents.md#6)** @@ -595,7 +640,7 @@ this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); **[*currentTransactionStatus*](windowsevents.md#4)** -Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*signatureRequired*](windowsevents.md#5)** @@ -649,7 +694,7 @@ this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "000000 **[*currentTransactionStatus*](windowsevents.md#4)** -Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*signatureRequired*](windowsevents.md#5)** @@ -739,7 +784,7 @@ this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "0000000 **[*currentTransactionStatus*](windowsevents.md#4)** -Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*signatureRequired*](windowsevents.md#5)** @@ -790,7 +835,7 @@ this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); **[*currentTransactionStatus*](windowsevents.md#4)** -Invoked during a transaction, it fetches statuses coming from the card reader (ex : 'waiting for card' or 'waiting for PIN entry') +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. **** **[*signatureRequired*](windowsevents.md#5)** diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md index bdc1929..869e710 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a device Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md index b4c2f73..d510c39 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsintegrationguide.md @@ -1370,13 +1370,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1509,7 +1509,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1573,7 +1573,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1824,7 +1824,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md index 09b7ce9..708770b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md index a4617db..ad1ce9b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsintegrationguide.md @@ -1386,13 +1386,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1525,7 +1525,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1589,7 +1589,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1840,7 +1840,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md index 09b7ce9..708770b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md index 545fde0..bf304be 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsintegrationguide.md @@ -1386,13 +1386,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1525,7 +1525,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1589,7 +1589,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1840,7 +1840,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md index 09b7ce9..708770b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md index e5739f8..b67db8a 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsintegrationguide.md @@ -1386,13 +1386,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1525,7 +1525,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1589,7 +1589,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1840,7 +1840,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md index 431e1dd..9779e51 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsobjects.md @@ -400,7 +400,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| ## Log Level{#9} diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md index 09b7ce9..708770b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md index 64c18e1..be11e25 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsintegrationguide.md @@ -1385,13 +1385,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1524,7 +1524,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1588,7 +1588,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1839,7 +1839,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md index 82f9be3..8dee292 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsobjects.md @@ -410,7 +410,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| | `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md index 1f3a441..0025273 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md @@ -25,11 +25,11 @@ Configures the device as the preferred device and tries to connect to it. Everyt Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); // The address is the composition of the serial number and model ot the target device. //Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 -api.UseDevice(device); +api.Connect(device); //Connect to a BLUETOOTH device (HiLite) Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); -api.UseDevice(device); +api.Connect(device); ``` #### Events invoked @@ -371,6 +371,7 @@ The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a res - UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. - IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. - REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. **Parameters** diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md index cce2377..b2604d1 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsintegrationguide.md @@ -1438,13 +1438,13 @@ At Handpoint we take care of securing every transaction so you don´t have to wo The SDK offers a method in which you will need to specify the card reader to be used: ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.****)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) ``` Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. ```csharp -hapi.useDevice(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) ``` ### Controlling responses @@ -1577,7 +1577,7 @@ Create a new C# class called MyClass and include com.handpoint.api as a dependen public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } ``` @@ -1641,7 +1641,7 @@ Let´s add 4 methods to MyClass in order to represent the 4 cases above : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() @@ -1892,7 +1892,7 @@ Here is how MyClass.cs and Form1.cs must eventually look like : public void Connect() { Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); - api.UseDevice(device); + api.Connect(device); } public bool PayWithSignatureAuthorized() diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md index 844878e..a3af3db 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsobjects.md @@ -415,7 +415,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| | `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| From 0ed5256c9dab78dac0cacd34a25d4bb704430e4c Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 19 Oct 2023 10:19:17 +0200 Subject: [PATCH 073/115] Preauth Rest Api (#93) Add: Card brand tables for PreAuth Capture Add: Card brand tables for PreAuth Capture Add: CAPTURED FinStatus Del: tip amount for PreAuth Increase & Capture --- android/androidobjects.md | 3 +- android/androidtransactions.md | 61 +++++++++++++--- javascript/javascriptobjects.md | 3 +- javascript/javascripttransactiontypes.md | 54 ++++++++++++-- restapi/restobjects.md | 91 ++++++++++++++++++++++-- windows/windowstransactions.md | 56 +++++++++++++-- 6 files changed, 240 insertions(+), 28 deletions(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index 470878c..e28fb17 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -393,7 +393,7 @@ An enum representing different statuses of a finalized transaction **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` Description of the different financial statuses: @@ -408,6 +408,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. diff --git a/android/androidtransactions.md b/android/androidtransactions.md index d74879b..e431892 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -6,7 +6,6 @@ id: androidtransactions # Transaction Types - ## Sale{#2} `Sale` @@ -775,7 +774,6 @@ This operation allows the merchant to increase the amount of a previously perfor | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| | `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| @@ -786,7 +784,7 @@ This operation allows the merchant to increase the amount of a previously perfor Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); -api.preAuthorizationIncrease(new BigInteger("1000"),Currency.GBP,new BigInteger("100"),"00000000-0000-0000-0000-000000000000", preauthOptions); +api.preAuthorizationIncrease(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); ``` **Events invoked** @@ -815,6 +813,14 @@ Invoked when the terminal finishes processing the transaction. A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | + **VISA rules** | MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | @@ -842,10 +848,9 @@ A pre-authorized transaction can be captured to actually debit the cardholder's **MASTERCARD rules** -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 5812 | Eating Places and Restaurants | 30 days | 20% | -| 5814 | Fast Food Restaurants | 30 days | 20% | +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | **Maestro rules** @@ -855,6 +860,39 @@ A pre-authorized transaction can be captured to actually debit the cardholder's | 5814 | Fast Food Restaurants | 7 days | 20% | +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +**Carte Bancaires** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 13 days | + + + + **Parameters** @@ -862,7 +900,6 @@ A pre-authorized transaction can be captured to actually debit the cardholder's | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `tipAmount`
*BigInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| | `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| @@ -873,7 +910,7 @@ A pre-authorized transaction can be captured to actually debit the cardholder's Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); -api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,new BigInteger("100"),"00000000-0000-0000-0000-000000000000", preauthOptions); +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); ``` **Events invoked** @@ -901,12 +938,16 @@ Invoked when the terminal finishes processing the transaction. A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. + +When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). But it cannot be reversed if the Settlement has already been done. + **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| | `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| **Code example** diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 5a787bd..87ddb65 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -479,7 +479,7 @@ An enum representing different statuses for a completed transaction. **Possible values** -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` Description of the different financial statuses: @@ -494,6 +494,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 9e41526..672371c 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -605,6 +605,15 @@ let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','0 A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | + **VISA rules** | MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | @@ -632,10 +641,9 @@ A pre-authorized transaction can be captured to actually debit the cardholder's **MASTERCARD rules** -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 5812 | Eating Places and Restaurants | 30 days | 20% | -| 5814 | Fast Food Restaurants | 30 days | 20% | +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | **Maestro rules** @@ -644,6 +652,38 @@ A pre-authorized transaction can be captured to actually debit the cardholder's | 5812 | Eating Places and Restaurants | 7 days | 20% | | 5814 | Fast Food Restaurants | 7 days | 20% | + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +**Carte Bancaires** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 13 days | + + **Parameters** @@ -675,7 +715,11 @@ let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00 `preAuthorizationReversal` A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. -A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. + +When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). But it cannot be reversed if the Settlement has already been done. **Parameters** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 2ef6816..d6107a6 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -43,10 +43,90 @@ Possible Values: | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | | `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | | `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | -| `preAuthorization`
*String* | Sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | -| `preAuthorizationIncrease`
*String* | It allows you to increase or decrease the initially pre-authorised amount before you capture it. | -| `preAuthorizationCapture`
*String* | Captures a pre-authorized credit card payment. | -| `preAuthorizationReversal`
*String* | Allows the merchant to reverse a previous pre-auth operation. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. | +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged.

A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed.

When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). But it cannot be reversed if the Settlement has already been done. | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +**Carte Bancaires** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 13 days | ## Financial Status{#financialStatus} @@ -54,7 +134,7 @@ Possible Values: An enum representing different statuses of a completed transaction. -`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` Description of the different financial statuses: @@ -69,6 +149,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 32d6295..7cb5ce8 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -720,6 +720,15 @@ This event is invoked when the transaction is completed, it contains the transac A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | + **VISA rules** | MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | @@ -747,10 +756,9 @@ A pre-authorized transaction can be captured to actually debit the cardholder's **MASTERCARD rules** -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 5812 | Eating Places and Restaurants | 30 days | 20% | -| 5814 | Fast Food Restaurants | 30 days | 20% | +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | **Maestro rules** @@ -759,6 +767,38 @@ A pre-authorized transaction can be captured to actually debit the cardholder's | 5812 | Eating Places and Restaurants | 7 days | 20% | | 5814 | Fast Food Restaurants | 7 days | 20% | + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +**Carte Bancaires** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 13 days | + + **Parameters** | Parameter | Notes | @@ -808,14 +848,18 @@ This event is invoked when the transaction is completed, it contains the transac `preAuthorizationReversal` A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. -A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. + +When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). But it cannot be reversed if the Settlement has already been done. **Parameters** | Parameter | Notes | | ----------- | ----------- | -| `originalTransactionID` Required
*String* |Transaction id of the original transaction| +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction| | `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| **Code example** From 481a044756972cda0fc2255efa1dcda1397d3e80 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 25 Oct 2023 14:20:32 +0200 Subject: [PATCH 074/115] Add: New terminals and features (#94) Add: New terminals and features Fix: PreAuth Capture tables and Reversals info. --- android/androidobjects.md | 2 +- android/androidtransactions.md | 24 ++-- javascript/javascriptobjects.md | 2 +- javascript/javascripttransactiontypes.md | 23 ++-- restapi/restobjects.md | 21 ++-- src/pages/cpdocs.js | 152 ++++++++++++++++++++++- windows/windowsobjects.md | 2 +- windows/windowstransactions.md | 23 ++-- 8 files changed, 208 insertions(+), 41 deletions(-) diff --git a/android/androidobjects.md b/android/androidobjects.md index e28fb17..34cc0d8 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -408,7 +408,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. diff --git a/android/androidtransactions.md b/android/androidtransactions.md index e431892..d1941ff 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -813,13 +813,16 @@ Invoked when the terminal finishes processing the transaction. A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. | Scheme | MCC | | ----------- | ----------- | | Mastercard | All MCCs except 5542 | | Visa | All MCCs except 5542 | | Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | **VISA rules** @@ -860,6 +863,15 @@ Card schemes set specific rules around which businesses are able to use pre-auth | 5814 | Fast Food Restaurants | 7 days | 20% | +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + **Discover rules** | MCC | Authorization timeframe | @@ -884,12 +896,6 @@ Card schemes set specific rules around which businesses are able to use pre-auth | All MCCs except Hotel and Car rental | 1 year | -**Carte Bancaires** - -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 13 days | - @@ -938,9 +944,7 @@ Invoked when the terminal finishes processing the transaction. A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. - -When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). But it cannot be reversed if the Settlement has already been done. +A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). **Parameters** diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 87ddb65..7c99103 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -494,7 +494,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index 672371c..e58933d 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -606,13 +606,17 @@ let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','0 A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + | Scheme | MCC | | ----------- | ----------- | | Mastercard | All MCCs except 5542 | | Visa | All MCCs except 5542 | | Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | **VISA rules** @@ -653,6 +657,14 @@ Card schemes set specific rules around which businesses are able to use pre-auth | 5814 | Fast Food Restaurants | 7 days | 20% | +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + **Discover rules** | MCC | Authorization timeframe | @@ -677,11 +689,6 @@ Card schemes set specific rules around which businesses are able to use pre-auth | All MCCs except Hotel and Car rental | 1 year | -**Carte Bancaires** - -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 13 days | **Parameters** @@ -717,9 +724,7 @@ let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00 A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. - -When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). But it cannot be reversed if the Settlement has already been done. +A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). **Parameters** diff --git a/restapi/restobjects.md b/restapi/restobjects.md index d6107a6..b596170 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -46,18 +46,22 @@ Possible Values: | `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | | `preAuthorizationIncrease`
*String* | This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. | | `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | -| `preAuthorizationReversal`
*String* | A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged.

A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed.

When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). But it cannot be reversed if the Settlement has already been done. | +| `preAuthorizationReversal`
*String* | A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged.

A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | ### Pre-Auth Capture Card Brand Rules -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + | Scheme | MCC | | ----------- | ----------- | | Mastercard | All MCCs except 5542 | | Visa | All MCCs except 5542 | | Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | **VISA rules** @@ -97,6 +101,12 @@ Card schemes set specific rules around which businesses are able to use pre-auth | 5812 | Eating Places and Restaurants | 7 days | 20% | | 5814 | Fast Food Restaurants | 7 days | 20% | +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. **Discover rules** @@ -122,11 +132,6 @@ Card schemes set specific rules around which businesses are able to use pre-auth | All MCCs except Hotel and Car rental | 1 year | -**Carte Bancaires** - -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 13 days | ## Financial Status{#financialStatus} @@ -149,7 +154,7 @@ Description of the different financial statuses: | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index b71ff2c..e7134f0 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -463,6 +463,43 @@ function TableTerminals() {

+
+
+
+
+
+

+ PAX A910S +

+
+ + +
+
+
+
+
+
+
+
+
+

+ PAX A920 MAX +

+
+ + +
+
+
+
+
+
+

@@ -571,6 +608,81 @@ function TableTerminals() {
+ +

+
+
+
+
+
+

+ PAX A800 +

+
+ + +
+
+
+
+
+
+
+
+
+

+ PAX A960 +

+
+ + +
+
+
+
+
+
+

+
+
+
+
+
+

+ PAX A6650 +

+
+ + +
+
+
+
+
+
+
+
+
+

+ PAX A8700 +

+
+ + +
+
+
+
+
+


@@ -1049,6 +1161,44 @@ function HighLevelFeatures() {


+
+
+
+
+
+

Tokenize & Modify

+
+
+

+ A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and + modify the amount before the transaction is sent for processing. +

+
+
+
+
+
+ +

+
+
+
+
+
+
+

PreAuth / Capture

+
+
+

+ A pre-auth initiates a pre-authorization operation to the card reader. + It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +

+
+
+
+
+
+

@@ -1079,7 +1229,7 @@ function HighLevelFeatures() {

Sends a refund operation to the payment terminal. This transaction type moves funds from the merchant account to the cardholder´s card. - in its simplest form you only need to send the amount and currency to the payment terminal for the transaction to start. + In its simplest form you only need to send the amount and currency to the payment terminal for the transaction to start.

diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index f8ca59d..bec54e5 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -395,7 +395,7 @@ An enum representing different final statuses of a transaction. | `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | | `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | | `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The transaction has been captured. The capture could be partial, so that an amount that is less than the authorized amount or the full authorized amount. However, the captured amount can't be an amount greater than the authorized amount. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](windowstransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 7cb5ce8..fa297a6 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -721,13 +721,17 @@ This event is invoked when the transaction is completed, it contains the transac A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Your eligibility is determined by your Merchant Category Code (MCC), together with the card scheme +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + | Scheme | MCC | | ----------- | ----------- | | Mastercard | All MCCs except 5542 | | Visa | All MCCs except 5542 | | Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | **VISA rules** @@ -768,6 +772,13 @@ Card schemes set specific rules around which businesses are able to use pre-auth | 5814 | Fast Food Restaurants | 7 days | 20% | +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + **Discover rules** | MCC | Authorization timeframe | @@ -792,12 +803,6 @@ Card schemes set specific rules around which businesses are able to use pre-auth | All MCCs except Hotel and Car rental | 1 year | -**Carte Bancaires** - -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 13 days | - **Parameters** @@ -850,9 +855,7 @@ This event is invoked when the transaction is completed, it contains the transac A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the preauthorization transaction is reversed, the withheld funds are released. But if it has been captured it cannot be reversed. - -When the capture is reverted, it returns to the previous state, that is, to preauthorization authorized and not captured ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). But it cannot be reversed if the Settlement has already been done. +A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). **Parameters** From ff586a69dbc1614ada224c62f656dddf9c5c831a Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 7 Nov 2023 14:22:49 +0100 Subject: [PATCH 075/115] Created new SDKs and REST API versions (#95) * Fix: Preauth for all SDKs and REST API * Update androidtransactions.md * Update androidtransactions.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restobjects.md * Update restobjects.md * Update windowstransactions.md * Update windowstransactions.md --------- Co-authored-by: Antoine --- android/androidreleasenotes.md | 6 +- android/androidtransactions.md | 20 +- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 415 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 +++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1168 ++++++++++ .../androidreleasenotes.md | 261 +++ .../androidtransactions.md | 995 ++++++++ ...version-Android SDK 7.1004.0-sidebars.json | 8 + android_versions.json | 1 + javascript/javascriptintroduction.md | 4 +- javascript/javascriptreleasenotes.md | 4 +- javascript/javascripttransactiontypes.md | 17 +- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 710 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 79 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 262 +++ .../javascripttransactiontypes.md | 759 +++++++ ...version-JavaScript SDK 7.1.0-sidebars.json | 8 + javascript_versions.json | 1 + restapi/restobjects.md | 6 +- restapi/restreleasenotes.md | 8 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.15.0/restdownloads.md | 10 + .../version-REST API 2.15.0/restendpoints.md | 427 ++++ .../restintroduction.md | 50 + .../version-REST API 2.15.0/restobjects.md | 797 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 84 + .../version-REST API 2.15.0/restsandbox.md | 44 + .../version-REST API 2.15.0-sidebars.json | 8 + restapi_versions.json | 1 + windows/windowsdevicemanagement.md | 33 - windows/windowsreleasenotes.md | 4 +- windows/windowstransactions.md | 17 +- .../windowsdevicemanagement.md | 33 - .../windowsdevicemanagement.md | 32 - .../windowsdevicemanagement.md | 33 - .../windowsdevicemanagement.md | 33 - .../windowsdevicemanagement.md | 33 - .../windowsdevicemanagement.md | 33 - .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 361 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 577 +++++ .../windowsreleasenotes.md | 94 + .../windowstransactions.md | 907 ++++++++ .../version-Windows SDK 4.1.0-sidebars.json | 8 + windows_versions.json | 1 + 59 files changed, 12549 insertions(+), 263 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1004.0-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.1.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.15.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.15.0-sidebars.json create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.1.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.1.0-sidebars.json diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 0fe2b69..c8ddd02 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,16 +11,16 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: -## 7.1003.0 +## 7.1004.0 **Features**: We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. -A pre-authorized transaction can be increased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increase)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be partially or fully released ([Pre-Auth Reversal](androidtransactions.md#pre-auth-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. ## 7.1002.0 diff --git a/android/androidtransactions.md b/android/androidtransactions.md index d1941ff..25b8f6d 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -761,11 +761,11 @@ Invoked when the terminal finishes processing the transaction. | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Pre-Auth Increase +## Pre-Auth Increase/Decrease `preAuthorizationIncrease` -This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. **Parameters** @@ -784,7 +784,13 @@ This operation allows the merchant to increase the amount of a previously perfor Options preauthOptions = new Options(); preauthOptions.setCustomerReference("CustomerReference"); -api.preAuthorizationIncrease(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); ``` **Events invoked** @@ -813,6 +819,8 @@ Invoked when the terminal finishes processing the transaction. A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. @@ -937,14 +945,14 @@ Invoked when the terminal finishes processing the transaction. | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Pre-Auth Reversal +## Pre-Auth/Capture Reversal `preAuthorizationReversal` A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. -A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). **Parameters** diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md new file mode 100644 index 0000000..5fb2f97 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md @@ -0,0 +1,415 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1004.0/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1004.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md new file mode 100644 index 0000000..34cc0d8 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md @@ -0,0 +1,1168 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md new file mode 100644 index 0000000..c8ddd02 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md @@ -0,0 +1,261 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidtransactions.md new file mode 100644 index 0000000..9d92ffa --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidtransactions.md @@ -0,0 +1,995 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.1004.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1004.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1004.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 84cdd2f..764d73d 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1004.0", "Android SDK 7.1002.0", "Android SDK 7.1001.0", "Android SDK 7.0.2", diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index 8a4b1f6..ad0d5ac 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index ec96312..992b6d5 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -14,11 +14,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. -A pre-authorized transaction can be increased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increase)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be partially or fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-auth-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. ## 7.0.0 **BREAKING CHANGE:** diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index e58933d..c112a9d 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -566,11 +566,12 @@ let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOp ``` -## Pre-Auth Increase +## Pre-Auth Increase/Decrease `preAuthorizationIncrease` -This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + **Parameters** @@ -590,6 +591,11 @@ This operation allows the merchant to increase the amount of a previously perfor let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { console.log('Transaction status received -> '+ stat.message) }); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); ``` **Returns** @@ -605,6 +611,7 @@ let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','0 A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. @@ -717,14 +724,14 @@ let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00 | ----------- | ----------- | | *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Pre-Auth Reversal +## Pre-Auth/Capture Reversal `preAuthorizationReversal` A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. -A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). **Parameters** diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptintroduction.md new file mode 100644 index 0000000..ad0d5ac --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md new file mode 100644 index 0000000..7c99103 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md @@ -0,0 +1,710 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + + + + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptquickintegration.md new file mode 100644 index 0000000..f5c935d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md new file mode 100644 index 0000000..992b6d5 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md @@ -0,0 +1,79 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..9a7c809 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptterminalmanagement.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascripttransactiontypes.md new file mode 100644 index 0000000..c112a9d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascripttransactiontypes.md @@ -0,0 +1,759 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.1.0-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.1.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.1.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index e59fe57..5fa54b8 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.1.0", "JavaScript SDK 7.0.0", "JavaScript SDK 6.3.0", "JavaScript SDK 6.2.1", diff --git a/restapi/restobjects.md b/restapi/restobjects.md index b596170..73576b6 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -44,9 +44,9 @@ Possible Values: | `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | | `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | | `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | -| `preAuthorizationIncrease`
*String* | This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. | -| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | -| `preAuthorizationReversal`
*String* | A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged.

A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | ### Pre-Auth Capture Card Brand Rules diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index dd7c888..3a58e6a 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -13,13 +13,13 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.15.0 **Features:** -We are introducing a new transaction type called Pre-Authorization. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. -A pre-authorized transaction can be increased, for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. -A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be partially or fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. diff --git a/restapi_versioned_docs/version-REST API 2.15.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.15.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md new file mode 100644 index 0000000..1ff98d8 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.15.0/restendpoints.md new file mode 100644 index 0000000..fae9914 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restendpoints.md @@ -0,0 +1,427 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does not use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +**Returns** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.15.0/restintroduction.md new file mode 100644 index 0000000..4ca8dfd --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restintroduction.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md new file mode 100644 index 0000000..73576b6 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md @@ -0,0 +1,797 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +```` + + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.15.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md new file mode 100644 index 0000000..3a58e6a --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md @@ -0,0 +1,84 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + + In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.15.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.15.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.15.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.15.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.15.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 53ad76d..66c68a1 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.15.0", "REST API 2.14.0", "REST API 2.13.0", "REST API 2.12.0", diff --git a/windows/windowsdevicemanagement.md b/windows/windowsdevicemanagement.md index f210b9e..99af86d 100644 --- a/windows/windowsdevicemanagement.md +++ b/windows/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| - ## Set logging level diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 140adc5..0d45728 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -14,11 +14,11 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. We are introducing a new transaction type called [Pre-Authorization](windowstransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. -A pre-authorized transaction can be increased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increase)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. A pre-authorized transaction can be captured ([Pre-Auth Capture](windowstransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be partially or fully released ([Pre-Auth Reversal](windowstransactions.md#pre-auth-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](windowstransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. ## 4.0.0 diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index fa297a6..664b792 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -660,11 +660,12 @@ This event is invoked when the transaction is completed, it contains the transac | *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Pre-Auth Increase +## Pre-Auth Increase/Decrease `preAuthorizationIncrease` -This operation allows the merchant to increase the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + **Parameters** @@ -680,7 +681,7 @@ This operation allows the merchant to increase the amount of a previously perfor **Code example** ```csharp -// Basic +// Basic PreAuth Increase this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); // With options @@ -689,6 +690,9 @@ map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); map.Add(XmlTag.Metadata1.Tag(), "Data 1"); this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); + +// Basic PreAuth Decrease +this.Hapi.PreAuthorizationIncrease(new BigInteger("-1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); ``` #### Events invoked @@ -720,6 +724,7 @@ This event is invoked when the transaction is completed, it contains the transac A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. @@ -848,14 +853,14 @@ This event is invoked when the transaction is completed, it contains the transac | ----------- | ----------- | | *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Pre-Auth Reversal +## Pre-Auth/Capture Reversal `preAuthorizationReversal` A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. -A pre-authorized transaction can be fully released, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized reversal transaction **will released the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](windowstransactions.md#pre-auth-increasedecrease) operation. -A Pre-Auth reversal can be used to reverse a capture operation as well. When the capture operation is reversed, the withheld funds are released. Reversing a capture operation can only be done before the funds are automatically settled at night. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). **Parameters** diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md index 869e710..fabb798 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to device.| -## Set parameter - -`SetParameter` - -Changes values of certain parameters on the card reader. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change| -| `value` Required
*String* | New value of the parameter| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the system which device you want to use for the operations. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to device.| - ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md index 708770b..c63c2aa 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsdevicemanagement.md @@ -108,38 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md index 708770b..c079df0 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| - ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md index 708770b..c079df0 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| - ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md index 708770b..c079df0 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| - ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md index 0025273..b0f6750 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsdevicemanagement.md @@ -108,39 +108,6 @@ No events invoked. | `Boolean`| `True` if the operation was successfully sent to the payment terminal.| -## Set parameter - -`SetParameter` Method - -Allows developers to optionally change several internal parameters of the payment terminal. - -#### Parameters - -| Parameter | Notes | -| ----------- | ----------- | -| `param` Required
[*DeviceParameter*](windowsobjects.md#8) | The name of the parameter to change.| -| `value` Required
*String* | New value of the parameter.| -| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| - -**Code example** - -```csharp -//Changes the bluetooth name of card reader -api.SetParameter(DeviceParameter.BluetoothName, "OrangeCardReader"); -``` - -#### Events invoked - -**None** - -No events are invoked. - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| - ## Set logging level diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsdevicemanagement.md new file mode 100644 index 0000000..99af86d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsdevicemanagement.md @@ -0,0 +1,361 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.Connect(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.Connect(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintegrationguide.md new file mode 100644 index 0000000..1ff930d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + // Put the name of your device + + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md new file mode 100644 index 0000000..bec54e5 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md @@ -0,0 +1,577 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + +## Terminal Parameters + + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](windowstransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + + +## Optional Transaction Parameters{#3} + + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + +## Verification Method{#29} + + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Hapi Manager + + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md new file mode 100644 index 0000000..0d45728 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md @@ -0,0 +1,94 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](windowstransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](windowstransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](windowstransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowstransactions.md new file mode 100644 index 0000000..664b792 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowstransactions.md @@ -0,0 +1,907 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +|`currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic PreAuth Increase +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); + +// Basic PreAuth Decrease +this.Hapi.PreAuthorizationIncrease(new BigInteger("-1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will released the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](windowstransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_sidebars/version-Windows SDK 4.1.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.1.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.1.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 2c7a2a1..3ab4649 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.1.0", "Windows SDK 4.0.0", "Windows SDK 3.4.0", "Windows SDK 3.3.0", From 4ca4f487604ed4df3f6081149c6218ff98eace70 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 8 Nov 2023 11:29:02 +0100 Subject: [PATCH 076/115] Add new terminals, T&M Release notes (#96) * Add: BP50+, more terminals and T&M release Notes * Fix * Update androidreleasenotes.md * Update androidreleasenotes.md * Update cpdocs.js --------- Co-authored-by: Antoine --- android/androidreleasenotes.md | 4 +- .../androidreleasenotes.md | 3 +- src/pages/cpdocs.js | 112 ++++++++++++++++-- static/img/HiPlus.png | Bin 0 -> 117185 bytes 4 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 static/img/HiPlus.png diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index c8ddd02..e706ab4 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -20,7 +20,9 @@ A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase]( A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. ## 7.1002.0 diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md index c8ddd02..9347a5e 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md @@ -20,8 +20,9 @@ A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase]( A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. -A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. ## 7.1002.0 **Features**: diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index e7134f0..5c079cc 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -392,7 +392,7 @@ function TableTerminals() {
-
+
@@ -409,7 +409,23 @@ function TableTerminals() {
-
+
+
+
+
+

+ HiLite Plus +

+
+ + cloud integration + +
+
+
+
+
+
@@ -491,7 +507,7 @@ function TableTerminals() {
@@ -600,7 +616,7 @@ function TableTerminals() {
@@ -608,7 +624,7 @@ function TableTerminals() {
- +

@@ -638,7 +654,7 @@ function TableTerminals() {
@@ -675,7 +691,7 @@ function TableTerminals() {
@@ -722,7 +738,7 @@ function CommunicationTypesTable() { Bluetooth Ethernet Cellular - Wifi + Wi-Fi @@ -734,7 +750,15 @@ function CommunicationTypesTable() { + + + HiLite Plus + + + + + @@ -746,6 +770,15 @@ function CommunicationTypesTable() { + + PAX A910S + + + + + + + PAX A920 @@ -765,6 +798,15 @@ function CommunicationTypesTable() { + + PAX A920 MAX + + + + + + + PAX A35 @@ -810,6 +852,51 @@ function CommunicationTypesTable() { + + PAX A800 + + + + + + + + + PAX A960 + + + + + + + + + PAX A6650 + + + + + + + + + PAX A8700 + + + + + + + + + PAX IM30 + + + + + + + Telpo TPS900 @@ -1170,8 +1257,9 @@ function HighLevelFeatures() {

- A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and - modify the amount before the transaction is sent for processing. + A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and + modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an + instant discount at the point of sale for loyal customers.

@@ -1190,8 +1278,8 @@ function HighLevelFeatures() {

- A pre-auth initiates a pre-authorization operation to the card reader. - It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + A pre-auth initiates a pre-authorization operation to the card reader. + It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront.

diff --git a/static/img/HiPlus.png b/static/img/HiPlus.png new file mode 100644 index 0000000000000000000000000000000000000000..45215af45440290fe6944bed56a1842e6dadfc44 GIT binary patch literal 117185 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

9T4puvqp;B4GSC`>Q7 zlb2WC-pzQonLrjl@2?4{GhQ59ojCgyy{Myrs2^bLP`)OAjkV3}YV^J@`-iBusyxyQ6$05uF#hx1Mb9EZ&uVx1!!8PYf3#Jg%mJ#HWpEG_8<9FXF^7o4? zn|p%=Rx=_PsA5fvf*rnAHss;0g*=wf(^b+o+3G30k}Zv%uCCx37^dVtvCa_v%0bQJ z{5v=EcZO@phlPtUl&0cHfJz_^KrE?FLw2=zl^>Gc;?-@kgU^6!!szwIU^b|14jWR` zxKvi4(gaRm_e_uA9etM^ejYt;^4>ZB`pfo=0Kt7k@LppgX&;?%c4L09xLu=Wjp97f z#rGA0W%@zRO3;c}ZvIYDRA1i1zY%_`y!iJbXuf*HZMU7a=HidC3pf(J!MS+o4#Pu7 z1g`sTi>sJI=FG;qsuu`v^?j{>RWxT!fNtr z805p0R9b>-A8+%wYWJ^2s1NFPe!9XL1CSovg_H~$U&)~cjNVXGiEH1dUZ{upjBw+w`+GuDlot-BaSw$a$`-?=G$N7m?;%B=oM@iVL8&!m ze10AgshQG)m;oYnGPP5>_ohHc0$sCJNKeDVyM2OZS2+*6^Ej zmlyeLyrd?5^O!L~edlb%myDsXhs|i(ny+($UczKE$rK)c%jiWxC{wRT z{PGOXWxFdQR{E8 zLQSe(grBgiCRj#rxxiGN{+bfwZ6cOqZ-GQ??vWL?p|+pv7jmp-3nxzl<+5)iRANH z=Daa~GlB|;gYJ2_geE4I`v;}um;&^Ql@S95_jG*(r>B8`S6V<q9c;M*U1!dy77 z`T#Cm?3!siX5*#uB~ew~f2HXxJ^x(I1qhG3NqBvG5}|yA>T~^tY;V32RHnW^3ITWZCXR%p+6#{8hd_y>f&S<^HbE0%Ds#s}n#ncs9< zf^L*2kJzmoVTFU z`MlSLkU+W2wzo*LxD;nH>>!{8AZE8&WqmcXA|7SMWmfx;0;w<&0~VBv8b_WBsANIa z{at?pH!J9d@YykWz9nfc2BoXEBDc~f-&9i86W*mh2yc}fNr#f zIU(a@m#``XpZH9i+c?lsCZWS`h7!#l%4(2V-K-5j;o_QArdLJ)jpEHtg-SWFRLE<# z2GFj5z+h|z@seaT7dwpMw5xAjdUtj^vL0l|qWiqw+!g#8jt5)Ku*vz-jyU}Hv^YAw zO?F;hAtPoOynpk*_z#}Vjy!+1zN|j+z4t+C6V&0<9(MmeAWkj>Y2n3q+xX66P0O`R zetsz9xA%-#CaVn#2}A3{*v~VY;pM}crBnr z(l&|!sg)6!A+eyqeQM*~fPdEj4W?{{MfmJ8up$vmGU_PDP`rVHbupMbqfPrN=-_H< zu&h;>f(twPm$@riqi?zN9}3VvTw?{b6K!%O5APpW;vzkZ>oOgR61Ncehx(EcPcUCjb?R+SeJJdhg&(~y|0IXRXZw8E~7-B#SKjI8;z4CgW0sL`y~hQ|OIhG8`$DkwW-(cV;IRWPlzSJcg-Uo9c4OHUp#R&-z{KpJvJG zF*1ramSSY<%8+gW{~si)IfyAla$7b{4NMZR>=B|0-+q4){BEQ~TJLj1SY&o1gXGPk zDVA7eSwo9E#X|FY(Y54@HRG}=o9nie--{%(-tsW9z}rj|T*$y9M;=O^Q3jNhU3^L% z>Ypqj@e&HJFiQSamhq#Khe}mJk}5`ZFFZpM)Ec2TOCBb0+;M3R%+_>X?bOJ9vuf-y z_!1V4vrubxApnYBbzjO7wvmJCJY<}3NFQ1V@!?Z07h%nsrt>lM2nUi*(r6AzU{LT( zzⓈ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 literal 0 HcmV?d00001 From 63d13cdef5e9d77a4a6c766430c1a02bfe88970c Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 24 Nov 2023 13:55:57 +0100 Subject: [PATCH 077/115] Add: Money Remittance docs (Android, JS, Win and REST API) (#98) * Add: Money Remittance docs (Android, JS, Win and REST API) * Update androidobjects.md * Update androidreleasenotes.md * Update androidobjects.md * Update androidreleasenotes.md * Update: Android SDK version (7.1004.1) * Update: REST API Postman Collection uodate * Update androidobjects.md * Update javascriptobjects.md * Update javascriptreleasenotes.md * Update restintroduction.md * Update restobjects.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowsobjects.md --------- Co-authored-by: Antoine --- android/androidobjects.md | 80 +- android/androidreleasenotes.md | 9 + javascript/javascriptobjects.md | 860 ++++++------ javascript/javascriptreleasenotes.md | 10 + .../javascriptobjects.md | 836 ++++++------ restapi/restdownloads.md | 2 +- restapi/restintroduction.md | 5 + restapi/restobjects.md | 1147 +++++++++-------- restapi/restreleasenotes.md | 8 + .../version-REST API 2.15.0/restobjects.md | 1123 ++++++++-------- .../files/Handpoint_API_REST_Nov2023.json.zip | Bin 0 -> 9784 bytes windows/windowsobjects.md | 730 ++++++----- windows/windowsreleasenotes.md | 12 + .../windowsobjects.md | 707 +++++----- 14 files changed, 2871 insertions(+), 2658 deletions(-) create mode 100644 static/files/Handpoint_API_REST_Nov2023.json.zip diff --git a/android/androidobjects.md b/android/androidobjects.md index c740c8f..a14e607 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -638,6 +638,57 @@ auth.add(credential); options.setMerchantAuth(auth); ``` +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + ## MoTo Channel `MoToChannel` Enum @@ -1140,33 +1191,4 @@ An enum representing different verification methods used in the transaction. `UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` -## Metadata{#metadata} -`Metadata` Object - -An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| - -**Code example** - -```java -// Option 1 -Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); - -// Option 2 -Metadata metadata = new Metadata(); -metadata.setMetadata1("Data 1"); -metadata.setMetadata2("Data 2"); -metadata.setMetadata3("Data 3"); -metadata.setMetadata4("Data 4"); -metadata.setMetadata5("Data 5"); -``` diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index ea8caed..9e5c2bb 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,15 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + ## 7.1004.0 **Features**: diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index c7cffe8..13eb281 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -6,141 +6,15 @@ id: javascriptobjects # Objects -## Transaction Result Object{#18} - -`TransactionResult` Object - -An object holding information about the result of a transaction. - -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. +## Acquirer{#21} -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: +`Acquirer` Enum -**Properties** +An enum representing the supported acquirers for merchant authentication -| Property | Description | -| ----------- | ----------- | -| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String * | Acquirer response code| -| `balance`
[*Balance*](#balance) | Balance available on the card| -| `budgetNumber`
*String * | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| -| `cardToken`
*String * | Token representing the PAN of the card| -| `chipTransactionReport`
*String * | Full report of the card EMV parameters| -| `currency`
[*Currency*](#31) | The currency used for the transaction| -| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | -| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String * | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String * | Response code from the card issuer| -| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| -| `merchantAddress`
*String * | Merchant Address| -| `merchantName`
*String * | Merchant Name| -| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `mid`
*String * | Merchant Identifier| -| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| -| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| -| `tid`
*String * | Terminal Identifier| -| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| -| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| -| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| -| `cardHolderName`
*String * | Name of the cardholder| +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` -**Code example** -```json -{ - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1":"data 1", - "metadata2":"data 2", - "metadata3":"data 3", - "metadata4":"data 4", - "metadata5":"data 5", - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "tipAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "tipPercentage": 0, - "recoveredTransaction": false, - "cardHolderName": "cardholder name" -} -``` ## Balance `Balance` Object @@ -191,6 +65,39 @@ Configuration to enable/disable signature or pin bypass. } ``` +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + ## Device{#20} `Device` Object @@ -219,97 +126,147 @@ An object to store information about the payment terminal in use. ALL values are } ``` -## Acquirer{#21} +## Device Status{#27} -`Acquirer` Enum +`DeviceStatus` Object -An enum representing the supported acquirers for merchant authentication +A class which holds the payment terminal status. -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` +**Properties** -## Transaction Status{#22} +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| -`TransactionStatus` Object +**Code example** -A class which holds the payment terminal status. This object is received in the financial operation callback. +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` +## Financial Status{#33} -**Properties** +`FinancialStatus` Enum -| Property | Description | -| ----------- | ----------- | -| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| -| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| -| `message`
*String* | Human readable status message.| -| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| +An enum representing different statuses for a completed transaction. -## Options{#26} +**Possible values** -`Options` Object +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` -An object to store all the customisation options for an operation. This object can be empty if no options are required. -**Properties** +Description of the different financial statuses: -| Property | Description | +| Parameter | Notes | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| - -**Code example** +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | -```json -{ - "customerReference": "MyCustomReference", - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -``` +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. -## Sale Options{#23} +## Merchant Auth{#17} -`SaleOptions` Object +`MerchantAuth` Object -An object to store the customization options for a sale operation. This object can be empty if no options are required. +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. **Properties** | Property | Description | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| -| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| -| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| -| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| **Code example** ```json { "customerReference": "MyCustomReference", - "duplicate_check": false, - "tipConfiguration": { - "baseAmount": "100", - "skipEnabled": true, - "enterAmountEnabled": true, - "tipPercentages": [ - 1, - 2, - 3, - 5 - ] - }, - "bypassOptions": { - "signatureBypass": true, - "pinBypass": true - }, "merchantAuth": [ { "acquirer": "ACQUIRER", @@ -318,6 +275,29 @@ An object to store the customization options for a sale operation. This object c "mcc": "33333" } ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ "metadata": { "metadata1": "data1", "metadata2": "data2", @@ -328,6 +308,84 @@ An object to store the customization options for a sale operation. This object c } ``` +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient.(**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + ## Refund Options{#24} `RefundOptions` Object @@ -385,24 +443,44 @@ An object to store the customization options for a refund. This object can be em } ``` -## Merchant Auth Options{#25} +## Sale Options{#23} -`MerchantAuthOptions` Object +`SaleOptions` Object -An object to store merchant authentication options for regular operations. +An object to store the customization options for a sale operation. This object can be empty if no options are required. **Properties** | Property | Description | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** ```json { "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, "merchantAuth": [ { "acquirer": "ACQUIRER", @@ -411,211 +489,44 @@ An object to store merchant authentication options for regular operations. "mcc": "33333" } ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ``` -## Merchant Auth{#17} -`MerchantAuth` Object +## Status{#38} -An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. +`status` Enum -**Properties** +An enum containing information about the status of a transaction. -| Property | Description | -| ----------- | ----------- | -| `Credential`
[*Credential[]*](#28) | Array of credentials.| +**Possible values** -**Code example** +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` -```json -{ - "merchantAuth": [{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333", - "externalId": "4444" - }] -} -``` -## Merchant Auth Credential{#28} +## Status Info -`Credential` Object +`statusInfo` Object -An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. +A class containing information about the status of the transaction. **Properties** | Property | Description | | ----------- | ----------- | -| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| -| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| -| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| -| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| -| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| -**Code example** - -```json -{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333" -} - -{ - "externalId": "4444" -} -``` - -## Financial Status{#33} - -`FinancialStatus` Enum - -An enum representing different statuses for a completed transaction. - -**Possible values** - -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` - - -Description of the different financial statuses: - -| Parameter | Notes | -| ----------- | ----------- | -| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | -| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | -| `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | -| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | -| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | - -\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. - - - - - -## Device Status{#27} - -`DeviceStatus` Object - -A class which holds the payment terminal status. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `SerialNumber`
*String * | The serial number of the payment terminal.| -| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| -| `BatterymV`
*String * | The battery millivolts of the payment terminal.| -| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| -| `ExternalPower`
*String * | The external power status of the payment terminal.| -| `ApplicationName`
*String * | The application name used by the payment terminal.| -| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| -| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| -| `statusMessage`
*String * | Status message of the payment terminal.| - -**Code example** - -```json -{ - "applicationName": "TestApp", - "applicationVersion": "20.1.0.1", - "batteryCharging": "Charging", - "batteryStatus": "100", - "batterymV": "4134", - "bluetoothName": "A920", - "externalPower": "USB", - "serialNumber": "0821032397", - "statusMessage": "Card reader time out" -} -``` - -## Currency{#31} - -`Currency` Enum - -An enum of currencies. - -**Possible values** - -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` - -## Card Entry Type{#29} - -`CardEntryType` Enum - -An enum representing different card entry types. - -**Possible values** - -`UNDEFINED` `MSR` `ICC` `CNP` - -## Card Scheme Name{#30} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - -## Verification Method{#37} - -`VerificationMethod` Enum - -An enum representing different cardholder verification methods. - -**Possible values** - -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - -## Payment Scenario{#34} - -`PaymentScenario` Enum - -An enum representing different types of payment scenario. - -**Possible values** - -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` - -## Status Info - -`statusInfo` Object - -A class containing information about the status of the transaction. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| -| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| -| `message`
*String* | A `string` containing the status message of the transaction.| -| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| - - -## Status{#38} - -`status` Enum - -An enum containing information about the status of a transaction. - -**Possible values** - -`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` - -## Tender Type{#35} +## Tender Type{#35} `TenderType` Enum @@ -625,6 +536,7 @@ An enum representing different tender types. `NOT_SET` `CREDIT` `DEBIT` + ## Tip Configuration{#39} `TipConfiguration` Object @@ -653,59 +565,179 @@ An object holding information about the configuration of the tipping menu for th footer: 'Thank you!!! ;)' } ``` +## Transaction Result Object{#18} -## Transaction Type{#36} - -`TransactionType` Enum - -An enum representing different types of transactions. - -**Possible values** - -`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` +`TransactionResult` Object -## Metadata{#metadata} +An object holding information about the result of a transaction. -`Metadata` Object +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -An object to store metadata. +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: **Properties** | Property | Description | | ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| **Code example** ```json { - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" } -``` - +``` +## Transaction Status{#22} -## Operation Start Result +`TransactionStatus` Object -`OperationStartResult` Object +A class which holds the payment terminal status. This object is received in the financial operation callback. -Object containing information about the financial operation being performed. **Properties** -| Parameter | Description | +| Property | Description | | ----------- | ----------- | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| -| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 992b6d5..7245f13 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -9,6 +9,16 @@ id: javascriptreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.2.0 +**Features:** + +We're excited to announce the latest update to our JavaScript SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](javascriptobjects.md#money-remittance-options)), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + ## 7.1.0 **Features**: diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md index 7c99103..f6e981c 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptobjects.md @@ -6,141 +6,15 @@ id: javascriptobjects # Objects -## Transaction Result Object{#18} - -`TransactionResult` Object - -An object holding information about the result of a transaction. - -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. +## Acquirer{#21} -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: +`Acquirer` Enum -**Properties** +An enum representing the supported acquirers for merchant authentication -| Property | Description | -| ----------- | ----------- | -| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String * | Acquirer response code| -| `balance`
[*Balance*](#balance) | Balance available on the card| -| `budgetNumber`
*String * | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| -| `cardToken`
*String * | Token representing the PAN of the card| -| `chipTransactionReport`
*String * | Full report of the card EMV parameters| -| `currency`
[*Currency*](#31) | The currency used for the transaction| -| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| -| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | -| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String * | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String * | Response code from the card issuer| -| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| -| `merchantAddress`
*String * | Merchant Address| -| `merchantName`
*String * | Merchant Name| -| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `mid`
*String * | Merchant Identifier| -| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| -| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| -| `tid`
*String * | Terminal Identifier| -| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| -| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| -| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| -| `cardHolderName`
*String * | Name of the cardholder| +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` -**Code example** -```json -{ - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1":"data 1", - "metadata2":"data 2", - "metadata3":"data 3", - "metadata4":"data 4", - "metadata5":"data 5", - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "tipAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "tipPercentage": 0, - "recoveredTransaction": false, - "cardHolderName": "cardholder name" -} -``` ## Balance `Balance` Object @@ -191,6 +65,39 @@ Configuration to enable/disable signature or pin bypass. } ``` +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + ## Device{#20} `Device` Object @@ -219,97 +126,147 @@ An object to store information about the payment terminal in use. ALL values are } ``` -## Acquirer{#21} +## Device Status{#27} -`Acquirer` Enum +`DeviceStatus` Object -An enum representing the supported acquirers for merchant authentication +A class which holds the payment terminal status. -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` +**Properties** -## Transaction Status{#22} +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| -`TransactionStatus` Object +**Code example** -A class which holds the payment terminal status. This object is received in the financial operation callback. +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` +## Financial Status{#33} -**Properties** +`FinancialStatus` Enum -| Property | Description | -| ----------- | ----------- | -| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| -| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| -| `message`
*String* | Human readable status message.| -| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| +An enum representing different statuses for a completed transaction. -## Options{#26} +**Possible values** -`Options` Object +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` -An object to store all the customisation options for an operation. This object can be empty if no options are required. -**Properties** +Description of the different financial statuses: -| Property | Description | +| Parameter | Notes | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| - -**Code example** +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | -```json -{ - "customerReference": "MyCustomReference", - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -``` +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. -## Sale Options{#23} +## Merchant Auth{#17} -`SaleOptions` Object +`MerchantAuth` Object -An object to store the customization options for a sale operation. This object can be empty if no options are required. +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. **Properties** | Property | Description | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| -| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| -| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| -| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| -| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| **Code example** ```json { "customerReference": "MyCustomReference", - "duplicate_check": false, - "tipConfiguration": { - "baseAmount": "100", - "skipEnabled": true, - "enterAmountEnabled": true, - "tipPercentages": [ - 1, - 2, - 3, - 5 - ] - }, - "bypassOptions": { - "signatureBypass": true, - "pinBypass": true - }, "merchantAuth": [ { "acquirer": "ACQUIRER", @@ -318,6 +275,29 @@ An object to store the customization options for a sale operation. This object c "mcc": "33333" } ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ "metadata": { "metadata1": "data1", "metadata2": "data2", @@ -328,6 +308,59 @@ An object to store the customization options for a sale operation. This object c } ``` +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + ## Refund Options{#24} `RefundOptions` Object @@ -385,24 +418,44 @@ An object to store the customization options for a refund. This object can be em } ``` -## Merchant Auth Options{#25} +## Sale Options{#23} -`MerchantAuthOptions` Object +`SaleOptions` Object -An object to store merchant authentication options for regular operations. +An object to store the customization options for a sale operation. This object can be empty if no options are required. **Properties** | Property | Description | | ----------- | ----------- | -| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** ```json { "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, "merchantAuth": [ { "acquirer": "ACQUIRER", @@ -411,247 +464,234 @@ An object to store merchant authentication options for regular operations. "mcc": "33333" } ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ``` -## Merchant Auth{#17} -`MerchantAuth` Object +## Status{#38} -An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. +`status` Enum -**Properties** +An enum containing information about the status of a transaction. -| Property | Description | -| ----------- | ----------- | -| `Credential`
[*Credential[]*](#28) | Array of credentials.| +**Possible values** -**Code example** +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` -```json -{ - "merchantAuth": [{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333", - "externalId": "4444" - }] -} -``` -## Merchant Auth Credential{#28} +## Status Info -`Credential` Object +`statusInfo` Object -An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. +A class containing information about the status of the transaction. **Properties** | Property | Description | | ----------- | ----------- | -| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| -| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| -| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| -| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| -| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| -**Code example** +## Tender Type{#35} -```json -{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333" -} +`TenderType` Enum -{ - "externalId": "4444" -} -``` +An enum representing different tender types. -## Financial Status{#33} +**Possible values** -`FinancialStatus` Enum +`NOT_SET` `CREDIT` `DEBIT` -An enum representing different statuses for a completed transaction. -**Possible values** +## Tip Configuration{#39} -`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` - -Description of the different financial statuses: - -| Parameter | Notes | -| ----------- | ----------- | -| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| -| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | -| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | -| `PROCESSED`
| The `printReceipt` operation was successful.| -| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | -| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | -| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | -| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | -| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | - -\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. - - - - - -## Device Status{#27} - -`DeviceStatus` Object +`TipConfiguration` Object -A class which holds the payment terminal status. +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. **Properties** | Property | Description | | ----------- | ----------- | -| `SerialNumber`
*String * | The serial number of the payment terminal.| -| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| -| `BatterymV`
*String * | The battery millivolts of the payment terminal.| -| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| -| `ExternalPower`
*String * | The external power status of the payment terminal.| -| `ApplicationName`
*String * | The application name used by the payment terminal.| -| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| -| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| -| `statusMessage`
*String * | Status message of the payment terminal.| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| **Code example** ```json { - "applicationName": "TestApp", - "applicationVersion": "20.1.0.1", - "batteryCharging": "Charging", - "batteryStatus": "100", - "batterymV": "4134", - "bluetoothName": "A920", - "externalPower": "USB", - "serialNumber": "0821032397", - "statusMessage": "Card reader time out" + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' } ``` +## Transaction Result Object{#18} -## Currency{#31} - -`Currency` Enum - -An enum of currencies. - -**Possible values** - -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` - -## Card Entry Type{#29} - -`CardEntryType` Enum - -An enum representing different card entry types. - -**Possible values** - -`UNDEFINED` `MSR` `ICC` `CNP` - -## Card Scheme Name{#30} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - -## Verification Method{#37} - -`VerificationMethod` Enum - -An enum representing different cardholder verification methods. - -**Possible values** - -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - -## Payment Scenario{#34} - -`PaymentScenario` Enum - -An enum representing different types of payment scenario. - -**Possible values** - -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` +`TransactionResult` Object -## Status Info +An object holding information about the result of a transaction. -`statusInfo` Object +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -A class containing information about the status of the transaction. +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: **Properties** | Property | Description | | ----------- | ----------- | -| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| -| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| -| `message`
*String* | A `string` containing the status message of the transaction.| -| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| - - -## Status{#38} - -`status` Enum - -An enum containing information about the status of a transaction. - -**Possible values** - -`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` - -## Tender Type{#35} - -`TenderType` Enum +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| -An enum representing different tender types. +**Code example** -**Possible values** +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` -`NOT_SET` `CREDIT` `DEBIT` +## Transaction Status{#22} -## Tip Configuration{#39} +`TransactionStatus` Object -`TipConfiguration` Object +A class which holds the payment terminal status. This object is received in the financial operation callback. -An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. **Properties** | Property | Description | | ----------- | ----------- | -| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| -| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| -| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| -| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| -| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| -| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| - -**Code example** +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| -```json -{ - baseAmount: '2000', - tipPercentages: [5,10,15,20,25], - enterAmountEnabled: true, - skipEnabled: false, - footer: 'Thank you!!! ;)' -} -``` ## Transaction Type{#36} @@ -663,48 +703,16 @@ An enum representing different types of transactions. `UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` -## Metadata{#metadata} - -`Metadata` Object - -An object to store metadata. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| - -**Code example** - -```json -{ - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -``` +## Verification Method{#37} +`VerificationMethod` Enum -## Operation Start Result +An enum representing different cardholder verification methods. -`OperationStartResult` Object +**Possible values** -Object containing information about the financial operation being performed. +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` -**Properties** -| Parameter | Description | -| ----------- | ----------- | -| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| -| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index 1ff98d8..9043092 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) diff --git a/restapi/restintroduction.md b/restapi/restintroduction.md index 4ca8dfd..5252785 100644 --- a/restapi/restintroduction.md +++ b/restapi/restintroduction.md @@ -40,6 +40,11 @@ The following flow shows the interactions between your application and the Handp **4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 73576b6..2b7609a 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -6,132 +6,168 @@ id: restobjects # Objects +## Acquirer -## Operation Type +`Acquirer` Enum -`OperationType` Enum +An enum representing the supported acquirers for merchant authentication. -An enum representing different types of operations. +**Possible values** +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` -Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` +## Balance +`Balance` Object -## Operation Types Description +Balance available on the card. -`OperationTypesDescription` +**Properties** -| Parameter | Notes | +| Property | Description | | ----------- | ----------- | -| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | -| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | -| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | -| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | -| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | -| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | -| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | -| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | -| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | -| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | -| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | -| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | -| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | -| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | -| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| -| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | -| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| +**Code example** -### Pre-Auth Capture Card Brand Rules +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. +## Bypass Options -Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. +`BypassOptions` Object -| Scheme | MCC | -| ----------- | ----------- | -| Mastercard | All MCCs except 5542 | -| Visa | All MCCs except 5542 | -| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | -| American Express | All MCCs except 5542 | -**VISA rules** +Configuration to enable/disable signature or pin bypass. -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 3501-3999, 7011 | Lodging | 31 days | 15% | -| 3351-3500, 7512 | Car Rental | 31 days | 15% | -| 4411 | Steamship and Cruise Lines | 31 days | 15% | -| 7513 | Truck Rentals | 7 days | 15% | -| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | -| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | -| 5552 | Electric Vehicle Charging | 7 days | 15% | -| 7523 | Parking and Garages | 7 days | 15% | -| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | -| 7999 | Recreation Services | 7 days | none | -| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | -| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | -| 4457 | Boat Rentals and Leasing | 7 days | none | -| 5571 | Motorcycle Shops and Dealers | 7 days | none | -| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | -| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | -| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | -| 5812 | Eating Places and Restaurants | Same day | 20% | -| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | -| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | -**MASTERCARD rules** +**Code example** -| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- | -| All MCCs | 30 days | 20% | +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` -**Maestro rules** +## Card Entry Type{#cardEntryType} -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 5812 | Eating Places and Restaurants | 7 days | 20% | -| 5814 | Fast Food Restaurants | 7 days | 20% | +`CardEntryType` Enum + +An enum representing different card entry types. -**AMEX rules** +**Possible values** -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 7 days | -Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. +`UNDEFINED` `MSR` `ICC` `CNP` -**Discover rules** -| MCC | Authorization timeframe | -| ----------- | ----------- | -| Car Rental, Hotel/Lodging MCCs | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | 10 days | +## Card Scheme Name {#cardSchemeName} -**Diners rules** +`CardSchemeName` Enum -| MCC | Debit/credit | Authorization timeframe | -| ----------- | ----------- | ----------- | -| Car Rental, Hotel/Lodging MCCs | All | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | +An enum representing different card brands. +**Possible values** -**JCB rules** +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| -| MCC | Authorization timeframe | -| ----------- | ----------- | -| Hotel and Car rental | Time of stay/rental | -| All MCCs except Hotel and Car rental | 1 year | +**Code example** +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` ## Financial Status{#financialStatus} @@ -159,148 +195,352 @@ Description of the different financial statuses: \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. +## Merchant Auth +`MerchantAuth` Object -## Transaction Result Object +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. -`TransactionResult` Object -An object holding information about the result of a transaction. +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. +**Code example** -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. **Properties** | Property | Description | | ----------- | ----------- | -| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String * | Acquirer response code| -| `balance`
[*Balance*](#balance) | Balance available on the card| -| `budgetNumber`
*String * | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| -| `cardToken`
*String * | Token representing the PAN of the card| -| `chipTransactionReport`
*String * | Full report of the card EMV parameters| -| `currency`
[*Currency*](#currency) | The currency used for the transaction| -| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| -| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| -| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String * | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String * | Response code from the card issuer| -| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| -| `merchantAddress`
*String * | Merchant Address| -| `merchantName`
*String * | Merchant Name| -| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| -| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `mid`
*String * | Merchant Identifier| -| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| -| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| -| `tid`
*String * | Terminal Identifier| -| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| -| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| -| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| -| `cardHolderName`
*String * | Name of the cardholder| -| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| **Code example** ````json { - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "tipAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "tipPercentage": 0, - "recoveredTransaction": false, - "cardHolderName": "Mr/Mrs card holder full name", - "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" } +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | -```` +**Code example** +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` ## Transaction Request Object {#transactionRequest} @@ -402,396 +642,195 @@ An object to store information about the request sent to the payment terminal. "duplicate_check": true, "metadata": { "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -```` - - -## Bypass Options - - -`BypassOptions` Object - - -Configuration to enable/disable signature or pin bypass. - -| Property | Description | -| ----------- | ----------- | -| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | -| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | - -**Code example** - -````json -{ - "bypassOptions": { - "signatureBypass": true, - "pinBypass": true - } -} -```` - -## Merchant Auth - -`MerchantAuth` Object - -An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. - - - -| Property | Description | -| ----------- | ----------- | -| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| - -**Code example** - -````json -{ - "merchantAuth": [{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333", - "externalId": "4444" - }] -} -```` - -## Acquirer - -`Acquirer` Enum - - -An enum representing the supported acquirers for merchant authentication. - -**Possible values** - -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` - - -## Device {#deviceObject} - -`Device` Object - - -An object to store information about the payment terminal in use. ALL values are **REQUIRED**. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| -| `serial_number` Required
*String* | Payment terminal serial number.| -| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| -| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| - -**Code example** - -````json -{ - "merchant_id_alpha": "Test_Merchant", - "serial_number": "614004878", - "ssk": "74817EA5C63437ADE7AA3A5401", - "terminal_type": "PAXA920" -} -```` - -## Currency - -`Currency` Enum - -An enum of currencies. - -**Possible values** - -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` - - - -## Card Entry Type{#cardEntryType} - -`CardEntryType` Enum - -An enum representing different card entry types. - -**Possible values** - -`UNDEFINED` `MSR` `ICC` `CNP` - - -## Verification Method{#verificationMethod} - - -`VerificationMethod` Enum - -An enum representing the possible verification methods used during the transaction. - -Possible values: - -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - - -## Merchant Auth Credential - -`Credential` Object - -An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| -| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| -| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| -| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| -| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| - -**Code example** - -````json -{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333" -} - -{ - "externalId": "4444" -} -```` - - -## Balance - -`Balance` Object - - -Balance available on the card. - - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `amount`
*Integer* | The balance| -| `currency`
*Currency* | The balance currency| -| `positive`
*Boolean* | Defines if the balance is positive| -| `negative`
*Boolean* | Defines if the balance is negative| - -**Code example** - -````json -"balance": { - "amount": 1000, - "currency": "EUR", - "negative": false, - "positive": true - } -```` - -## Device Status{#deviceStatus} - -`DeviceStatus` Object - - -A class which holds the payment terminal status. - - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `SerialNumber`
*String* | The serial number of the payment terminal.| -| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| -| `BatterymV`
*String* | The battery milli volts of the payment terminal.| -| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| -| `ExternalPower`
*String* | The status of the external power of the payment terminal.| -| `ApplicationName`
*String* | The application name used on the payment terminal.| -| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| -| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| -| `statusMessage`
*String* | Device human readable status message.| - - -**Code example** - -````json -{ - "applicationName": "TestApp", - "applicationVersion": "20.1.0.1", - "batteryCharging": "Charging", - "batteryStatus": "100", - "batterymV": "4134", - "bluetoothName": "A920", - "externalPower": "USB", - "serialNumber": "0821032397", - "statusMessage": "Card reader time out" + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ```` -## Card Scheme Name {#cardSchemeName} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - - - -## Transaction Type{#transactionType} - -`TransactionType` Enum - -An enum representing different types of transactions. - -**Possible values** - -`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` - - -## Payment Scenario{#paymentScenario} - - -`PaymentScenario` Enum - - -An enum representing different types of payment scenario. -**Possible values** +## Transaction Result Object -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` +`TransactionResult` Object -## Status Info -`StatusInfo` Object +An object holding information about the result of a transaction. +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -A class containing information about the status of the transaction. +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: **Properties** | Property | Description | | ----------- | ----------- | -| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | -| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | -| `message`
*String* | A `String` containing the status message of the transaction. | -| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +**Code example** -## Status +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} -`status` Enum +```` -An enum containing information about the status of a transaction. +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. **Possible values** -`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` -## Tip Configuration +## Verification Method{#verificationMethod} -`TipConfiguration` Object +`VerificationMethod` Enum -| Property | Description | -| ----------- | ----------- | -| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | -| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | -| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | -| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | -| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | -| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | +An enum representing the possible verification methods used during the transaction. -**Code example** +Possible values: -````json -{ - "tipConfiguration":{ - "baseAmount":"2000", - "headerName":"", - "tipPercentages":[ - 5, - 10, - 15, - 20, - 25 - ], - "enterAmountEnabled":true, - "skipEnabled":false, - "footer":"Thank you!!! ;)" - } - } -```` +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` -## Tender Type{#tenderType} -`TenderType` Enum -An enum representing different tender types. -Possible values -`NOT_SET` `CREDIT` `DEBIT` -## Tip Adjustment -`TipAdjustment` Object -| Property | Description | -| ----------- | ----------- | -| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | -**Code example** -````json -{ - "amount": 10.25 -} -{ - "amount": 20 -} -```` -## Metadata{#metadata} -`Metadata` Object -An object to store metadata. -**Properties** -| Property | Description | -| ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -**Code example** -```json -{ - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -``` diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index e282619..54553fd 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,14 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 2.16.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. ## 2.15.0 **Features:** diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md index 73576b6..6a4fa2a 100644 --- a/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.15.0/restobjects.md @@ -6,132 +6,168 @@ id: restobjects # Objects +## Acquirer -## Operation Type +`Acquirer` Enum -`OperationType` Enum +An enum representing the supported acquirers for merchant authentication. -An enum representing different types of operations. +**Possible values** +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` -Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` +## Balance +`Balance` Object -## Operation Types Description +Balance available on the card. -`OperationTypesDescription` +**Properties** -| Parameter | Notes | +| Property | Description | | ----------- | ----------- | -| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | -| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | -| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | -| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | -| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | -| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | -| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | -| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | -| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | -| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | -| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | -| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | -| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | -| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | -| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | -| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| -| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | -| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| +**Code example** -### Pre-Auth Capture Card Brand Rules +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` -Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. +## Bypass Options -Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. +`BypassOptions` Object -| Scheme | MCC | -| ----------- | ----------- | -| Mastercard | All MCCs except 5542 | -| Visa | All MCCs except 5542 | -| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | -| American Express | All MCCs except 5542 | -**VISA rules** +Configuration to enable/disable signature or pin bypass. -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 3501-3999, 7011 | Lodging | 31 days | 15% | -| 3351-3500, 7512 | Car Rental | 31 days | 15% | -| 4411 | Steamship and Cruise Lines | 31 days | 15% | -| 7513 | Truck Rentals | 7 days | 15% | -| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | -| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | -| 5552 | Electric Vehicle Charging | 7 days | 15% | -| 7523 | Parking and Garages | 7 days | 15% | -| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | -| 7999 | Recreation Services | 7 days | none | -| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | -| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | -| 4457 | Boat Rentals and Leasing | 7 days | none | -| 5571 | Motorcycle Shops and Dealers | 7 days | none | -| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | -| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | -| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | -| 5812 | Eating Places and Restaurants | Same day | 20% | -| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | -| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | -**MASTERCARD rules** +**Code example** -| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- | -| All MCCs | 30 days | 20% | +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` -**Maestro rules** +## Card Entry Type{#cardEntryType} -| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | -| ----------- | ----------- | ----------- |----------- | -| 5812 | Eating Places and Restaurants | 7 days | 20% | -| 5814 | Fast Food Restaurants | 7 days | 20% | +`CardEntryType` Enum + +An enum representing different card entry types. -**AMEX rules** +**Possible values** -| MCC | Authorization timeframe | -| ----------- | ----------- | -| All MCCs | 7 days | -Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. +`UNDEFINED` `MSR` `ICC` `CNP` -**Discover rules** -| MCC | Authorization timeframe | -| ----------- | ----------- | -| Car Rental, Hotel/Lodging MCCs | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | 10 days | +## Card Scheme Name {#cardSchemeName} -**Diners rules** +`CardSchemeName` Enum -| MCC | Debit/credit | Authorization timeframe | -| ----------- | ----------- | ----------- | -| Car Rental, Hotel/Lodging MCCs | All | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | -| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | +An enum representing different card brands. +**Possible values** -**JCB rules** +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| -| MCC | Authorization timeframe | -| ----------- | ----------- | -| Hotel and Car rental | Time of stay/rental | -| All MCCs except Hotel and Car rental | 1 year | +**Code example** +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` ## Financial Status{#financialStatus} @@ -159,148 +195,328 @@ Description of the different financial statuses: \* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. +## Merchant Auth +`MerchantAuth` Object -## Transaction Result Object +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. -`TransactionResult` Object -An object holding information about the result of a transaction. +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. +**Code example** -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. **Properties** | Property | Description | | ----------- | ----------- | -| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String * | Acquirer response code| -| `balance`
[*Balance*](#balance) | Balance available on the card| -| `budgetNumber`
*String * | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| -| `cardToken`
*String * | Token representing the PAN of the card| -| `chipTransactionReport`
*String * | Full report of the card EMV parameters| -| `currency`
[*Currency*](#currency) | The currency used for the transaction| -| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| -| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| -| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| -| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String * | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String * | Response code from the card issuer| -| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| -| `merchantAddress`
*String * | Merchant Address| -| `merchantName`
*String * | Merchant Name| -| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| -| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `mid`
*String * | Merchant Identifier| -| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| -| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| -| `tid`
*String * | Terminal Identifier| -| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| -| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| -| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| -| `cardHolderName`
*String * | Name of the cardholder| -| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| **Code example** ````json { - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "tipAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "tipPercentage": 0, - "recoveredTransaction": false, - "cardHolderName": "Mr/Mrs card holder full name", - "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" } -```` +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` ## Transaction Request Object {#transactionRequest} @@ -402,396 +618,195 @@ An object to store information about the request sent to the payment terminal. "duplicate_check": true, "metadata": { "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -```` - - -## Bypass Options - - -`BypassOptions` Object - - -Configuration to enable/disable signature or pin bypass. - -| Property | Description | -| ----------- | ----------- | -| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | -| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | - -**Code example** - -````json -{ - "bypassOptions": { - "signatureBypass": true, - "pinBypass": true - } -} -```` - -## Merchant Auth - -`MerchantAuth` Object - -An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. - - - -| Property | Description | -| ----------- | ----------- | -| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| - -**Code example** - -````json -{ - "merchantAuth": [{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333", - "externalId": "4444" - }] -} -```` - -## Acquirer - -`Acquirer` Enum - - -An enum representing the supported acquirers for merchant authentication. - -**Possible values** - -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` - - -## Device {#deviceObject} - -`Device` Object - - -An object to store information about the payment terminal in use. ALL values are **REQUIRED**. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| -| `serial_number` Required
*String* | Payment terminal serial number.| -| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| -| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| - -**Code example** - -````json -{ - "merchant_id_alpha": "Test_Merchant", - "serial_number": "614004878", - "ssk": "74817EA5C63437ADE7AA3A5401", - "terminal_type": "PAXA920" -} -```` - -## Currency - -`Currency` Enum - -An enum of currencies. - -**Possible values** - -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` - - - -## Card Entry Type{#cardEntryType} - -`CardEntryType` Enum - -An enum representing different card entry types. - -**Possible values** - -`UNDEFINED` `MSR` `ICC` `CNP` - - -## Verification Method{#verificationMethod} - - -`VerificationMethod` Enum - -An enum representing the possible verification methods used during the transaction. - -Possible values: - -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - - -## Merchant Auth Credential - -`Credential` Object - -An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| -| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| -| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| -| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| -| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| - -**Code example** - -````json -{ - "acquirer": "ACQ_DUMMY", - "mid": "1111", - "tid": "2222", - "mcc": "3333" -} - -{ - "externalId": "4444" -} -```` - - -## Balance - -`Balance` Object - - -Balance available on the card. - - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `amount`
*Integer* | The balance| -| `currency`
*Currency* | The balance currency| -| `positive`
*Boolean* | Defines if the balance is positive| -| `negative`
*Boolean* | Defines if the balance is negative| - -**Code example** - -````json -"balance": { - "amount": 1000, - "currency": "EUR", - "negative": false, - "positive": true - } -```` - -## Device Status{#deviceStatus} - -`DeviceStatus` Object - - -A class which holds the payment terminal status. - - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `SerialNumber`
*String* | The serial number of the payment terminal.| -| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| -| `BatterymV`
*String* | The battery milli volts of the payment terminal.| -| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| -| `ExternalPower`
*String* | The status of the external power of the payment terminal.| -| `ApplicationName`
*String* | The application name used on the payment terminal.| -| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| -| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| -| `statusMessage`
*String* | Device human readable status message.| - - -**Code example** - -````json -{ - "applicationName": "TestApp", - "applicationVersion": "20.1.0.1", - "batteryCharging": "Charging", - "batteryStatus": "100", - "batterymV": "4134", - "bluetoothName": "A920", - "externalPower": "USB", - "serialNumber": "0821032397", - "statusMessage": "Card reader time out" + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } } ```` -## Card Scheme Name {#cardSchemeName} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - - - -## Transaction Type{#transactionType} - -`TransactionType` Enum - -An enum representing different types of transactions. - -**Possible values** - -`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` - - -## Payment Scenario{#paymentScenario} - - -`PaymentScenario` Enum - - -An enum representing different types of payment scenario. -**Possible values** +## Transaction Result Object -`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` +`TransactionResult` Object -## Status Info -`StatusInfo` Object +An object holding information about the result of a transaction. +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -A class containing information about the status of the transaction. +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: **Properties** | Property | Description | | ----------- | ----------- | -| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | -| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | -| `message`
*String* | A `String` containing the status message of the transaction. | -| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +**Code example** -## Status +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} -`status` Enum +```` -An enum containing information about the status of a transaction. +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. **Possible values** -`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` -## Tip Configuration +## Verification Method{#verificationMethod} -`TipConfiguration` Object +`VerificationMethod` Enum -| Property | Description | -| ----------- | ----------- | -| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | -| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | -| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | -| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | -| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | -| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | +An enum representing the possible verification methods used during the transaction. -**Code example** +Possible values: -````json -{ - "tipConfiguration":{ - "baseAmount":"2000", - "headerName":"", - "tipPercentages":[ - 5, - 10, - 15, - 20, - 25 - ], - "enterAmountEnabled":true, - "skipEnabled":false, - "footer":"Thank you!!! ;)" - } - } -```` +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` -## Tender Type{#tenderType} -`TenderType` Enum -An enum representing different tender types. -Possible values -`NOT_SET` `CREDIT` `DEBIT` -## Tip Adjustment -`TipAdjustment` Object -| Property | Description | -| ----------- | ----------- | -| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | -**Code example** -````json -{ - "amount": 10.25 -} -{ - "amount": 20 -} -```` -## Metadata{#metadata} -`Metadata` Object -An object to store metadata. -**Properties** -| Property | Description | -| ----------- | ----------- | -| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -**Code example** -```json -{ - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } -} -``` diff --git a/static/files/Handpoint_API_REST_Nov2023.json.zip b/static/files/Handpoint_API_REST_Nov2023.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..eb9a4a197543f1b3a4b8165a92cc35ba52f87642 GIT binary patch literal 9784 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 C`xf~C literal 0 HcmV?d00001 diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index bec54e5..4ed63dc 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -6,244 +6,60 @@ id: windowobjects # Objects -## Transaction Result Object{#14} - -`TransactionResult` Object - -An object holding information about the result of a transaction. - -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. - -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: - -**Properties** - -| Parameter | Notes | -| ----------- | ----------- | -| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String* | Acquirer response code| -| `balance`
*BigInteger* | Balance available on the card| -| `budgetNumber`
*String* | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| -| `cardToken`
*String* | Token representing the PAN of the card| -| `chipTransactionReport`
*String* | Full report of the card EMV parameters| -| `currency`
[*Currency*](#1) | The currency used for the transaction| -| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| -| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String* | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String* | Response code from the card issuer| -| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| -| `merchantAddress`
*String* | Merchant Address| -| `merchantName`
*String* | Merchant Name| -| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| -| `mid`
*String* | Merchant Identifier| -| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| -| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| -| `tid`
*String* | Terminal Identifier| -| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| - -**Code example** - -```json -{ - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1": "Data 1", - "metadata2": "", - "metadata3": "", - "metadata4": "", - "metadata5": "" - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "gratuityAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "gratuityPercentage": 0, - "recoveredTransaction": false -} -``` +## Card Entry Type{#22} -## Handpoint Credentials{#30} +`CardEntryType` Enum -`HandpointCredentials` Object +An enum representing different card entry types. -A class containing information related to the user credentials. +** Possible values ** -**Properties** +`UNDEFINED` `MSR` `ICC` `CNP` -| Parameter | Notes | -| ----------- | ----------- | -| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| -| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| +## Card Scheme Name{#23} -**Code example** +`CardSchemeName` Enum -```csharp -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - new HandpointCredentials(sharedSecret); - //We've set a default shared secret! -} - -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - string apikey = "This-Is-The-Merchant-Api-Key"; - new HandpointCredentials(sharedSecret, apikey); - //We've set a default shared secret and the merchant Api Key! -} -``` +An enum representing different card brands. -## Handpoint API (Hapi) factory +**Possible values** -`HapiFactory` Object +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` -A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. -**Methods** +## Connection Method{#12} -**Static factory** -getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); +`ConnectionMethod` Enum -| Parameter | Notes | -| ----------- | ----------- | -| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| -| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| +An enum representing different types of connection methods. -**Code example** +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. -```csharp -//InitApi for HiLite payment terminals -public void InitApi() -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); - //The api is now initialized. Yay! we've even set a default shared secret -} +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` -//InitApi for Cloud payment terminals (PAX/Telpo) -public void InitApi() -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - string apikey = "This-Is-The-Merchant-Api-Key"; - api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); - //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! -} -``` -## Transaction Type{#28} +## Connection Status{#18} -`TransactionType` Enum +`ConnectionStatus` Enum -An enum representing different types of transactions. +A list of statuses given to a connection. **Possible values** -`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` -## Connection Method{#12} -`ConnectionMethod` Enum +## Currency{#1} -An enum representing different types of connection methods. +`Currency` Enum -`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. +An enum of currencies. -Possible values -`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` +**Possible values** -**Code example** +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` -```csharp -//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. -public enum ConnectionMethod -{ - USB, - SERIAL, - HTTPS, - WIFI, - ETHERNET, - BLUETOOTH, - CLOUD, - SIMULATOR -} -``` ## Device{#2} @@ -251,8 +67,6 @@ public enum ConnectionMethod An object to store the information about the payment terminal in use. -**Methods** - **Constructor** Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); @@ -284,67 +98,26 @@ Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMetho | `Id`
*String* | A unique identifier for the device.| -## Connection Status{#18} +## Device Parameter{#8} -`ConnectionStatus` Enum -A list of statuses given to a connection. +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. **Possible values** -`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` -## Currency{#1} -`Currency` Enum -An enum of currencies. +## Device Status{#24} -**Possible values** -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` +`DeviceStatus` Enum -## Signature Request{#17} - -`SignatureRequest` Object - -A class containing information about a signature request or verification. - -**Properties** - -|Property| Description| -| ----------- | ----------- | -|Timeout
*Int* |The value of the timeout in seconds.| -|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | - -## Card Scheme Name{#23} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - -## Device Parameter{#8} - - -`DeviceParameter` Enum - -An enum describing all the available commands to send to a device. - -**Possible values** - -`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` -`Language` - -## Device Status{#24} - - -`DeviceStatus` Enum - -A class that holds the device status. +A class that holds the device status. **Properties** @@ -358,17 +131,6 @@ A class that holds the device status. |`ApplicationName`
*String*| Gets the application name used by the device.| |`ApplicationVersion`
*String*| Gets the application version number used by the device.| -## Terminal Parameters - - -`TerminalType` Enum - -An enum describing parameters supported by the payment terminal. - -**Possible values** - -`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` -`Language` ## Financial Status{#25} @@ -401,27 +163,100 @@ An enum representing different final statuses of a transaction. +## Handpoint API (Hapi) factory -## Optional Transaction Parameters{#3} +`HapiFactory` Object +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. -`OptionalParameters` Object +**Methods** -A class containing optional transaction parameters now supported by the device. +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. **Properties** +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| -|Property| Description| +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| | ----------- | ----------- | -|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| -|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| -| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` ## Log Level{#9} @@ -436,33 +271,91 @@ An enum describing the different levels of logging used in the SDK and the payme `None` `Info` `Full` `Debug` -## Status Info {#statusInfo} +## Metadata{#metadata} -`statusInfo` Object +`Metadata` Object -A class containing information about the status of the transaction. +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemitanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. **Properties** +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```csharp +Dictionary map = new Dictionary(); + +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +``` + + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. |Property |Description| | ----------- | ----------- | -|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| -|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| -|`message`
*String* |A `String` containing the status message of the transaction.| -|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| -## Verification Method{#29} +## Optional Transaction Parameters{#3} + +`OptionalParameters` Object -`VerificationMethod` Enum +A class containing optional transaction parameters now supported by the device. -An enum representing different cardholder verification methods. +**Properties** -** Possible values ** -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` - `MOBILE_PASS_CODE` +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| ## Payment Scenario{#26} @@ -475,6 +368,21 @@ An enum representing different types of payment scenarios. `UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + + ## Status `status` Enum @@ -485,6 +393,24 @@ An enum containing information about the status of the transaction. `Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + + ## Tender Type{#27} `TenderType` Enum @@ -495,83 +421,195 @@ An enum representing different tender types. `NOT_SET` `CREDIT` `DEBIT` -## Card Entry Type{#22} -`CardEntryType` Enum +## Terminal Parameters -An enum representing different card entry types. +`TerminalType` Enum -** Possible values ** +An enum describing parameters supported by the payment terminal. -`UNDEFINED` `MSR` `ICC` `CNP` +**Possible values** +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` -## Hapi Manager -`HapiManager` Object +## Transaction Result Object{#14} -A static class containing information about the current status of the SDK +`TransactionResult` Object -** Properties ** +An object holding information about the result of a transaction. +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -|Property |Description| +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | | ----------- | ----------- | -|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| -|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| -|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| -|`SdkVersion`
*String* |Gets the current Sdk version.| -|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| -|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| **Code example** -```csharp -//Check if the SDK is in transaction -bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); -//Check the current logLevel -LogLevel level = HapiManager.GetLogLevel(); +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} ``` -## Metadata{#metadata} -`Metadata` Object +## Transaction Type{#28} -Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . +`TransactionType` Enum -**Properties** +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` -| Property | Description | -| ----------- | ----------- | -| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** -```json +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod { - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR } -``` +``` + + +## Verification Method{#29} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` -## Operation Start Result{#OperationStartResult} -`OperationStartResult` Object -Object containing information about the financial operation being performed. -|Property |Description| -| ----------- | ----------- | -|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| -|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| -|`ErrorMessage`
*String* |Detailed reason for the transaction error.| diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 0d45728..b84f0c9 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -9,6 +9,18 @@ id: windowsreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: + +## 4.2.0 +**Features:** + +We're excited to announce the latest update to our Windows SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](windowsobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is only available for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + + ## 4.1.0 **Features**: diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md index bec54e5..89c33fc 100644 --- a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsobjects.md @@ -6,244 +6,60 @@ id: windowobjects # Objects -## Transaction Result Object{#14} - -`TransactionResult` Object - -An object holding information about the result of a transaction. - -:::tip -`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. - -`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. -::: - -**Properties** - -| Parameter | Notes | -| ----------- | ----------- | -| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| -| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| -| `authorisationCode`
*String* | Acquirer response code| -| `balance`
*BigInteger* | Balance available on the card| -| `budgetNumber`
*String* | Used to split payments over a period of months| -| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| -| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| -| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| -| `cardToken`
*String* | Token representing the PAN of the card| -| `chipTransactionReport`
*String* | Full report of the card EMV parameters| -| `currency`
[*Currency*](#1) | The currency used for the transaction| -| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| -| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| -| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| -| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| -| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| -| `errorMessage`
*String* | Detailed reason for the transaction error| -| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| -| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| -| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| -| `issuerResponseCode`
*String* | Response code from the card issuer| -| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| -| `merchantAddress`
*String* | Merchant Address| -| `merchantName`
*String* | Merchant Name| -| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | -| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| -| `mid`
*String* | Merchant Identifier| -| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| -| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| -| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| -| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| -| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| -| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| -| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| -| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| -| `tid`
*String* | Terminal Identifier| -| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| -| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| -| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| -| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| -| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| -| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| -| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| -| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| - -**Code example** - -```json -{ - "aid": "A0000000041010", - "arc": "0000", - "authorisationCode": "123456", - "balance": null, - "budgetNumber": "", - "cardEntryType": "UNDEFINED", - "cardLanguagePreference": "", - "cardSchemeName": "MasterCard", - "cardToken": "", - "chipTransactionReport": "", - "currency": "USD", - "customerReceipt": "https://s3.[...]/customerReceipt.html", - "customerReference": "", - "deviceStatus": { - "applicationName": "ClientApp", - "applicationVersion": "20.1.0", - "batteryCharging": "Not Charging", - "batteryStatus": "100", - "batterymV": "4126", - "bluetoothName": "PAXA920", - "externalPower": "USB", - "serialNumber": "0821032398", - "statusMessage": "Approved or completed successfully" - }, - "dueAmount": 0, - "errorMessage": "", - "expiryDateMMYY": "0422", - "finStatus": "AUTHORISED", - "iad": "0210A000002A0000000000000000000000FF", - "issuerResponseCode": "00", - "maskedCardNumber": "************1456", - "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", - "merchantName": "Hago la cama", - "merchantReceipt": "https://s3.[...]/merchantReceipt.html", - "metadata": { - "metadata1": "Data 1", - "metadata2": "", - "metadata3": "", - "metadata4": "", - "metadata5": "" - }, - "mid": "", - "originalEFTTransactionID": "", - "paymentScenario": "CHIPCONTACTLESS", - "rrn": "", - "signatureUrl": "", - "statusMessage": "Approved or completed successfully", - "tenderType": "CREDIT", - "tid": "ACQUIRER_TID", - "gratuityAmount": 0, - "totalAmount": 100, - "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "tsi": "0000", - "tvr": "0400008001", - "type": "SALE", - "unMaskedPan": "", - "verificationMethod": "UNDEFINED", - "efttimestamp": 1615374961000, - "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", - "requestedAmount": 100, - "gratuityPercentage": 0, - "recoveredTransaction": false -} -``` +## Card Entry Type{#22} -## Handpoint Credentials{#30} +`CardEntryType` Enum -`HandpointCredentials` Object +An enum representing different card entry types. -A class containing information related to the user credentials. +** Possible values ** -**Properties** +`UNDEFINED` `MSR` `ICC` `CNP` -| Parameter | Notes | -| ----------- | ----------- | -| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| -| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| +## Card Scheme Name{#23} -**Code example** +`CardSchemeName` Enum -```csharp -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - new HandpointCredentials(sharedSecret); - //We've set a default shared secret! -} - -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - string apikey = "This-Is-The-Merchant-Api-Key"; - new HandpointCredentials(sharedSecret, apikey); - //We've set a default shared secret and the merchant Api Key! -} -``` +An enum representing different card brands. -## Handpoint API (Hapi) factory +**Possible values** -`HapiFactory` Object +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` -A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. -**Methods** +## Connection Method{#12} -**Static factory** -getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); +`ConnectionMethod` Enum -| Parameter | Notes | -| ----------- | ----------- | -| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| -| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| +An enum representing different types of connection methods. -**Code example** +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. -```csharp -//InitApi for HiLite payment terminals -public void InitApi() -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); - //The api is now initialized. Yay! we've even set a default shared secret -} +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` -//InitApi for Cloud payment terminals (PAX/Telpo) -public void InitApi() -{ - string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - string apikey = "This-Is-The-Merchant-Api-Key"; - api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); - //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! -} -``` -## Transaction Type{#28} +## Connection Status{#18} -`TransactionType` Enum +`ConnectionStatus` Enum -An enum representing different types of transactions. +A list of statuses given to a connection. **Possible values** -`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` -## Connection Method{#12} -`ConnectionMethod` Enum +## Currency{#1} -An enum representing different types of connection methods. +`Currency` Enum -`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. +An enum of currencies. -Possible values -`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` +**Possible values** -**Code example** +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` -```csharp -//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. -public enum ConnectionMethod -{ - USB, - SERIAL, - HTTPS, - WIFI, - ETHERNET, - BLUETOOTH, - CLOUD, - SIMULATOR -} -``` ## Device{#2} @@ -251,8 +67,6 @@ public enum ConnectionMethod An object to store the information about the payment terminal in use. -**Methods** - **Constructor** Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); @@ -284,67 +98,26 @@ Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMetho | `Id`
*String* | A unique identifier for the device.| -## Connection Status{#18} +## Device Parameter{#8} -`ConnectionStatus` Enum -A list of statuses given to a connection. +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. **Possible values** -`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` -## Currency{#1} -`Currency` Enum -An enum of currencies. +## Device Status{#24} -**Possible values** -`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` +`DeviceStatus` Enum -## Signature Request{#17} - -`SignatureRequest` Object - -A class containing information about a signature request or verification. - -**Properties** - -|Property| Description| -| ----------- | ----------- | -|Timeout
*Int* |The value of the timeout in seconds.| -|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | - -## Card Scheme Name{#23} - -`CardSchemeName` Enum - -An enum representing different card brands. - -**Possible values** - -`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` - -## Device Parameter{#8} - - -`DeviceParameter` Enum - -An enum describing all the available commands to send to a device. - -**Possible values** - -`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` -`Language` - -## Device Status{#24} - - -`DeviceStatus` Enum - -A class that holds the device status. +A class that holds the device status. **Properties** @@ -358,17 +131,6 @@ A class that holds the device status. |`ApplicationName`
*String*| Gets the application name used by the device.| |`ApplicationVersion`
*String*| Gets the application version number used by the device.| -## Terminal Parameters - - -`TerminalType` Enum - -An enum describing parameters supported by the payment terminal. - -**Possible values** - -`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` -`Language` ## Financial Status{#25} @@ -401,27 +163,100 @@ An enum representing different final statuses of a transaction. +## Handpoint API (Hapi) factory -## Optional Transaction Parameters{#3} +`HapiFactory` Object +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. -`OptionalParameters` Object +**Methods** -A class containing optional transaction parameters now supported by the device. +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. **Properties** +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** -|Property| Description| +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| | ----------- | ----------- | -|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| -|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| -| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` ## Log Level{#9} @@ -436,33 +271,68 @@ An enum describing the different levels of logging used in the SDK and the payme `None` `Info` `Full` `Debug` -## Status Info {#statusInfo} +## Metadata{#metadata} -`statusInfo` Object +`Metadata` Object -A class containing information about the status of the transaction. +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . **Properties** +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. |Property |Description| | ----------- | ----------- | -|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| -|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| -|`message`
*String* |A `String` containing the status message of the transaction.| -|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| -## Verification Method{#29} +## Optional Transaction Parameters{#3} -`VerificationMethod` Enum +`OptionalParameters` Object -An enum representing different cardholder verification methods. +A class containing optional transaction parameters now supported by the device. -** Possible values ** +**Properties** -`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` - `MOBILE_PASS_CODE` + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| ## Payment Scenario{#26} @@ -475,6 +345,21 @@ An enum representing different types of payment scenarios. `UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + + ## Status `status` Enum @@ -485,6 +370,24 @@ An enum containing information about the status of the transaction. `Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + + ## Tender Type{#27} `TenderType` Enum @@ -495,83 +398,195 @@ An enum representing different tender types. `NOT_SET` `CREDIT` `DEBIT` -## Card Entry Type{#22} -`CardEntryType` Enum +## Terminal Parameters -An enum representing different card entry types. +`TerminalType` Enum -** Possible values ** +An enum describing parameters supported by the payment terminal. -`UNDEFINED` `MSR` `ICC` `CNP` +**Possible values** +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` -## Hapi Manager -`HapiManager` Object +## Transaction Result Object{#14} -A static class containing information about the current status of the SDK +`TransactionResult` Object -** Properties ** +An object holding information about the result of a transaction. +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. -|Property |Description| +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | | ----------- | ----------- | -|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| -|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| -|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| -|`SdkVersion`
*String* |Gets the current Sdk version.| -|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| -|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| **Code example** -```csharp -//Check if the SDK is in transaction -bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); -//Check the current logLevel -LogLevel level = HapiManager.GetLogLevel(); +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} ``` -## Metadata{#metadata} -`Metadata` Object +## Transaction Type{#28} -Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . +`TransactionType` Enum -**Properties** +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` -| Property | Description | -| ----------- | ----------- | -| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| -| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| **Code example** -```json +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod { - "metadata": { - "metadata1": "data1", - "metadata2": "data2", - "metadata3": "data3", - "metadata4": "data4", - "metadata5": "data5" - } + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR } -``` +``` + + +## Verification Method{#29} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` -## Operation Start Result{#OperationStartResult} -`OperationStartResult` Object -Object containing information about the financial operation being performed. -|Property |Description| -| ----------- | ----------- | -|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| -|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| -|`ErrorMessage`
*String* |Detailed reason for the transaction error.| From bc4af7d36e82127f7cef4564158aaf090dbaf56b Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 29 Nov 2023 13:55:15 +0100 Subject: [PATCH 078/115] Add: New versions (Money Remittance) (#99) --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 416 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 +++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1194 ++++++++++ .../androidreleasenotes.md | 273 +++ .../androidtransactions.md | 995 ++++++++ ...version-Android SDK 7.1004.1-sidebars.json | 8 + android_versions.json | 1 + javascript/javascriptintroduction.md | 4 +- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 743 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 89 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 262 +++ .../javascripttransactiontypes.md | 759 +++++++ ...version-JavaScript SDK 7.2.0-sidebars.json | 8 + javascript_versions.json | 1 + restapi/restreleasenotes.md | 2 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.17.0/restdownloads.md | 10 + .../version-REST API 2.17.0/restendpoints.md | 427 ++++ .../restintroduction.md | 55 + .../version-REST API 2.17.0/restobjects.md | 836 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 92 + .../version-REST API 2.17.0/restsandbox.md | 44 + .../version-REST API 2.17.0-sidebars.json | 8 + restapi_versions.json | 1 + .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 361 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 +++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 615 +++++ .../windowsreleasenotes.md | 106 + .../windowstransactions.md | 907 ++++++++ .../version-Windows SDK 4.2.0-sidebars.json | 8 + windows_versions.json | 1 + 45 files changed, 12683 insertions(+), 3 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1004.1-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.2.0-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.17.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.17.0-sidebars.json create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.2.0-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md new file mode 100644 index 0000000..bf46b10 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md @@ -0,0 +1,416 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("12345"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1004.1/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1004.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +

+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md new file mode 100644 index 0000000..a14e607 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md @@ -0,0 +1,1194 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md new file mode 100644 index 0000000..9e5c2bb --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md @@ -0,0 +1,273 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md new file mode 100644 index 0000000..e0e6a10 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md @@ -0,0 +1,995 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.1004.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1004.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1004.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 764d73d..bd1fb02 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1004.1", "Android SDK 7.1004.0", "Android SDK 7.1002.0", "Android SDK 7.1001.0", diff --git a/javascript/javascriptintroduction.md b/javascript/javascriptintroduction.md index ad0d5ac..3b63fd1 100644 --- a/javascript/javascriptintroduction.md +++ b/javascript/javascriptintroduction.md @@ -13,12 +13,12 @@ id: javascriptintroduction

JavaScript SDK

diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptintroduction.md new file mode 100644 index 0000000..3b63fd1 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md new file mode 100644 index 0000000..13eb281 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md @@ -0,0 +1,743 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient.(**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptquickintegration.md new file mode 100644 index 0000000..f5c935d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md new file mode 100644 index 0000000..7245f13 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.2.0 +**Features:** + +We're excited to announce the latest update to our JavaScript SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](javascriptobjects.md#money-remittance-options)), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptterminalmanagement.md new file mode 100644 index 0000000..9a7c809 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptterminalmanagement.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md new file mode 100644 index 0000000..c112a9d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md @@ -0,0 +1,759 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.2.0-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 5fa54b8..275fc24 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.2.0", "JavaScript SDK 7.1.0", "JavaScript SDK 7.0.0", "JavaScript SDK 6.3.0", diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 54553fd..a58bc3a 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,7 +9,7 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: -## 2.16.0 +## 2.17.0 **Features:** We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. diff --git a/restapi_versioned_docs/version-REST API 2.17.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.17.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md new file mode 100644 index 0000000..9043092 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.17.0/restendpoints.md new file mode 100644 index 0000000..fae9914 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restendpoints.md @@ -0,0 +1,427 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does not use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +**Returns** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.17.0/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md new file mode 100644 index 0000000..2b7609a --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md @@ -0,0 +1,836 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + + + + + + + + + + + + + + + + + + diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.17.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md new file mode 100644 index 0000000..a58bc3a --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md @@ -0,0 +1,92 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.17.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.17.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.17.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.17.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.17.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 66c68a1..c006714 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.17.0", "REST API 2.15.0", "REST API 2.14.0", "REST API 2.13.0", diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsdevicemanagement.md new file mode 100644 index 0000000..99af86d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsdevicemanagement.md @@ -0,0 +1,361 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.Connect(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.Connect(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintegrationguide.md new file mode 100644 index 0000000..1ff930d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + // Put the name of your device + + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md new file mode 100644 index 0000000..4ed63dc --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md @@ -0,0 +1,615 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](windowstransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemitanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```csharp +Dictionary map = new Dictionary(); + +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +``` + + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| + + +## Optional Transaction Parameters{#3} + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Terminal Parameters + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + + +## Verification Method{#29} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md new file mode 100644 index 0000000..b84f0c9 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md @@ -0,0 +1,106 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 4.2.0 +**Features:** + +We're excited to announce the latest update to our Windows SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](windowsobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is only available for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + + +## 4.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](windowstransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](windowstransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](windowstransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md new file mode 100644 index 0000000..664b792 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md @@ -0,0 +1,907 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +|`currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic PreAuth Increase +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); + +// Basic PreAuth Decrease +this.Hapi.PreAuthorizationIncrease(new BigInteger("-1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will released the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](windowstransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_sidebars/version-Windows SDK 4.2.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.2.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.2.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 3ab4649..05d3885 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.2.0", "Windows SDK 4.1.0", "Windows SDK 4.0.0", "Windows SDK 3.4.0", From 1f8765ab9bf624d9f9f5cbfa679b04743e5ed8b1 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 30 Nov 2023 12:02:44 +0100 Subject: [PATCH 079/115] Add mremittance examples (#101) * Add: Money Remittance code examples * Upd: Postman Collection with MRemittance examples --- android/androidobjects.md | 20 ++++++++ android/androidtransactions.md | 46 +++++++++++++++--- .../androidobjects.md | 20 ++++++++ .../androidtransactions.md | 38 ++++++++++++--- javascript/javascriptobjects.md | 10 ++++ javascript/javascripttransactiontypes.md | 32 +++++++++--- .../javascriptobjects.md | 11 +++++ .../javascripttransactiontypes.md | 34 ++++++++++--- restapi/restdownloads.md | 2 +- restapi/restobjects.md | 13 ++++- .../version-REST API 2.17.0/restdownloads.md | 2 +- .../version-REST API 2.17.0/restobjects.md | 13 ++++- ...I_REST_Nov2023.postman_collection.json.zip | Bin 0 -> 9854 bytes windows/windowsobjects.md | 1 + windows/windowstransactions.md | 43 +++++++++++++--- .../windowsobjects.md | 1 + .../windowstransactions.md | 38 ++++++++++++--- 17 files changed, 281 insertions(+), 43 deletions(-) create mode 100644 static/files/API_REST_Nov2023.postman_collection.json.zip diff --git a/android/androidobjects.md b/android/androidobjects.md index a14e607..67ba846 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -712,6 +712,7 @@ An object to store optional parameters for card not present (MoTo) transactions. | `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| | `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| | `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| @@ -724,6 +725,10 @@ options.setTokenize(true); options.setTokenize(false); options.setChannel(MoToChannel.MO); options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); ``` ## Operation DTO @@ -843,6 +848,7 @@ An object to store all the customization options for a refund. | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| | `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -874,6 +880,10 @@ options.setCheckDuplicates(false); // Metadata Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); ``` ## Report Configuration{#19} @@ -920,6 +930,7 @@ An object to store all the customization options for a sale. | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| | `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -972,6 +983,10 @@ options.setTipConfiguration(new TipConfiguration(AMOUNT)); // Metadata Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); ``` ## Sale and Tokenize Options @@ -989,6 +1004,7 @@ An object to store all the customization options for a sale and tokenize options | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -1037,6 +1053,10 @@ options.setTipConfiguration(config); //Alternatively, you can set the tip amount directly options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); ``` diff --git a/android/androidtransactions.md b/android/androidtransactions.md index e0e6a10..3070c67 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -20,7 +20,7 @@ A sale initiates a payment operation to the card reader. In it's simplest form y | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -45,6 +45,13 @@ options.setTipConfiguration(tipConfiguration); options.setMetadata(metadata); api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); ``` **Events invoked** @@ -82,7 +89,7 @@ A [sale](#2) operation which also returns a card token. (not available for all a | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -107,6 +114,12 @@ options.setTipConfiguration(tipConfiguration); options.toSaleAndTokenizeOptions(); api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); ``` **Events invoked** @@ -195,13 +208,19 @@ A refund operation moves funds from the merchant account to the cardholder´s cr | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** ```java -//Initiate a refund for 10.00 in Great British Pounds +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); ``` ** Events invoked** @@ -289,15 +308,23 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** ```java +//Initiate a MoTo sale for 10.00 in Great British Pounds MoToOptions options = new MoToOptions(); options.setCustomerReference("MoTo Sale Example"); api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + ``` **Events invoked** @@ -337,7 +364,7 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -346,6 +373,13 @@ MoToOptions options = new MoToOptions(); options.setCustomerReference("MoTo Refund Example"); api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); ``` **Events invoked** diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md index a14e607..67ba846 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md @@ -712,6 +712,7 @@ An object to store optional parameters for card not present (MoTo) transactions. | `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| | `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| | `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| @@ -724,6 +725,10 @@ options.setTokenize(true); options.setTokenize(false); options.setChannel(MoToChannel.MO); options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); ``` ## Operation DTO @@ -843,6 +848,7 @@ An object to store all the customization options for a refund. | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| | `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -874,6 +880,10 @@ options.setCheckDuplicates(false); // Metadata Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); ``` ## Report Configuration{#19} @@ -920,6 +930,7 @@ An object to store all the customization options for a sale. | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| | `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -972,6 +983,10 @@ options.setTipConfiguration(new TipConfiguration(AMOUNT)); // Metadata Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); ``` ## Sale and Tokenize Options @@ -989,6 +1004,7 @@ An object to store all the customization options for a sale and tokenize options | `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| | `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| | `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -1037,6 +1053,10 @@ options.setTipConfiguration(config); //Alternatively, you can set the tip amount directly options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); ``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md index e0e6a10..2f4e88b 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidtransactions.md @@ -20,7 +20,7 @@ A sale initiates a payment operation to the card reader. In it's simplest form y | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -45,6 +45,11 @@ options.setTipConfiguration(tipConfiguration); options.setMetadata(metadata); api.sale(new BigInteger("1000"),Currency.GBP, options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); ``` **Events invoked** @@ -82,7 +87,7 @@ A [sale](#2) operation which also returns a card token. (not available for all a | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale.| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -107,6 +112,11 @@ options.setTipConfiguration(tipConfiguration); options.toSaleAndTokenizeOptions(); api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); ``` **Events invoked** @@ -195,13 +205,18 @@ A refund operation moves funds from the merchant account to the cardholder´s cr | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund.| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** ```java -//Initiate a refund for 10.00 in Great British Pounds +////Initiate a refund for 10.00 in Great British Pounds (Linked Refund) api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); ``` ** Events invoked** @@ -289,15 +304,21 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| -| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** ```java +//Initiate a MoTo sale for 10.00 in Great British Pounds MoToOptions options = new MoToOptions(); options.setCustomerReference("MoTo Sale Example"); api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); ``` **Events invoked** @@ -337,7 +358,7 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| | `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| | `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| **Code example** @@ -346,6 +367,11 @@ MoToOptions options = new MoToOptions(); options.setCustomerReference("MoTo Refund Example"); api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); ``` **Events invoked** diff --git a/javascript/javascriptobjects.md b/javascript/javascriptobjects.md index 13eb281..9a93cc0 100644 --- a/javascript/javascriptobjects.md +++ b/javascript/javascriptobjects.md @@ -403,6 +403,7 @@ An object to store the customization options for a refund. This object can be em | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -439,6 +440,10 @@ An object to store the customization options for a refund. This object can be em "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" } } ``` @@ -459,6 +464,7 @@ An object to store the customization options for a sale operation. This object c | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -495,6 +501,10 @@ An object to store the customization options for a sale operation. This object c "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" } } ``` diff --git a/javascript/javascripttransactiontypes.md b/javascript/javascripttransactiontypes.md index c112a9d..928fddc 100644 --- a/javascript/javascripttransactiontypes.md +++ b/javascript/javascripttransactiontypes.md @@ -18,7 +18,7 @@ A sale initiates a transaction with the payment terminal. In its simplest form, | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale ([Tip Configuration](javascriptobjects.md#39), [Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -55,6 +55,10 @@ var saleOptions = { metadata3: "data3", metadata4: "data4", metadata5: "data5" + }, + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" } } @@ -87,7 +91,7 @@ A sale operation which also returns a card token. This functionality is not avai | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale and tokenize ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -118,6 +122,10 @@ var saleOptions = { mcc: "33333" } ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { @@ -221,7 +229,7 @@ A refund initiates a transaction with the payment terminal. This operation moves | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| | `originalTransactionID`
*string* | The transaction id of the original sale authorization.| -| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -241,6 +249,10 @@ var refundOptions = { mcc: "33333" } ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); @@ -316,7 +328,7 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a MOTO sale (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -324,6 +336,10 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP ```javascript var saleOptions = { customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { @@ -355,14 +371,18 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| | `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** ```javascript var refundOptions = { - customerReference: "MyCustomReference" + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md index 13eb281..1d0d60e 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptobjects.md @@ -403,6 +403,7 @@ An object to store the customization options for a refund. This object can be em | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -439,7 +440,12 @@ An object to store the customization options for a refund. This object can be em "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" } + } ``` @@ -459,6 +465,7 @@ An object to store the customization options for a sale operation. This object c | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| **Code example** @@ -495,6 +502,10 @@ An object to store the customization options for a sale operation. This object c "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" } } ``` diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md index c112a9d..1648860 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascripttransactiontypes.md @@ -18,7 +18,7 @@ A sale initiates a transaction with the payment terminal. In its simplest form, | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale ([Tip Configuration](javascriptobjects.md#39), [Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -55,7 +55,11 @@ var saleOptions = { metadata3: "data3", metadata4: "data4", metadata5: "data5" - } + }, + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { @@ -87,7 +91,7 @@ A sale operation which also returns a card token. This functionality is not avai | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale. This object can be empty if no options are required.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale and tokenize ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -118,6 +122,10 @@ var saleOptions = { mcc: "33333" } ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { @@ -221,7 +229,7 @@ A refund initiates a transaction with the payment terminal. This operation moves | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| | `originalTransactionID`
*string* | The transaction id of the original sale authorization.| -| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund. This object can be empty if no options are required.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -241,6 +249,10 @@ var refundOptions = { mcc: "33333" } ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); @@ -316,7 +328,7 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| -| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** @@ -324,6 +336,10 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP ```javascript var saleOptions = { customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { @@ -355,14 +371,18 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*string* | Currency of the transaction.| | `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund. This object can be empty if no options are required.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO refund (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| | `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| **Code example** ```javascript var refundOptions = { - customerReference: "MyCustomReference" + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } } let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index 9043092..5ce5eb3 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 19beaa9..68af6f1 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -569,6 +569,7 @@ An object to store information about the request sent to the payment terminal. | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | **Code example** @@ -609,7 +610,11 @@ An object to store information about the request sent to the payment terminal. "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" - } + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } } // Result will be served back to Handpoint's REST-API @@ -646,7 +651,11 @@ An object to store information about the request sent to the payment terminal. "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" - } + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } } ```` diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md index 9043092..5ce5eb3 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md @@ -7,4 +7,4 @@ id: restapidownloads Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). -[Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md index 2b7609a..0734fde 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restobjects.md @@ -569,6 +569,7 @@ An object to store information about the request sent to the payment terminal. | `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | **Code example** @@ -609,7 +610,11 @@ An object to store information about the request sent to the payment terminal. "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" - } + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } } // Result will be served back to Handpoint's REST-API @@ -646,7 +651,11 @@ An object to store information about the request sent to the payment terminal. "metadata3": "data3", "metadata4": "data4", "metadata5": "data5" - } + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } } ```` diff --git a/static/files/API_REST_Nov2023.postman_collection.json.zip b/static/files/API_REST_Nov2023.postman_collection.json.zip new file mode 100644 index 0000000000000000000000000000000000000000..239a2d60e66b362e3481b2a9fe412cd24dadface GIT binary patch literal 9854 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 D^ra{M literal 0 HcmV?d00001 diff --git a/windows/windowsobjects.md b/windows/windowsobjects.md index d639358..311e005 100644 --- a/windows/windowsobjects.md +++ b/windows/windowsobjects.md @@ -357,6 +357,7 @@ A class containing optional transaction parameters now supported by the device. | `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](windowsobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| ## Payment Scenario{#26} diff --git a/windows/windowstransactions.md b/windows/windowstransactions.md index 664b792..c013743 100644 --- a/windows/windowstransactions.md +++ b/windows/windowstransactions.md @@ -22,7 +22,7 @@ A sale initiates a transaction with the payment terminal. In it's simplest form | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** @@ -35,6 +35,8 @@ this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); Dictionary map = new Dictionary(); map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); map.Add(XmlTag.Metadata1.Tag(), "Data 1"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); ``` @@ -76,13 +78,21 @@ A sale operation which also returns a card token. This functionality is not avai | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp //Initiate a sale for 10.00 in Great British Pounds api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.SaleAndTokenizeCard(new BigInteger("1000"), Currency.EUR, map); ``` #### Events invoked @@ -168,13 +178,22 @@ A refund operation moves funds from the merchant account to the cardholder´s cr | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| | `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp //Initiate a refund for 10.00 in Great British Pounds api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.Refund(new BigInteger("1000"), Currency.EUR, map); ``` #### Events invoked @@ -259,17 +278,19 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*Currency* | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp -// Basic +// Basic MoTo Sale this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); // With options Dictionary dic = new Dictionary(); dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); ``` @@ -305,14 +326,24 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required*Currency* | Currency of the transaction.| | `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp +//Basic MoTo Refund this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + + +//With Options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.MotoRefund(new BigInteger("1000"), Currency.EUR, dic); ``` #### Events invoked diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md index 4ed63dc..647d6eb 100644 --- a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsobjects.md @@ -356,6 +356,7 @@ A class containing optional transaction parameters now supported by the device. | `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](windowsobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| ## Payment Scenario{#26} diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md index 664b792..ae75618 100644 --- a/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowstransactions.md @@ -22,7 +22,7 @@ A sale initiates a transaction with the payment terminal. In it's simplest form | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** @@ -35,6 +35,8 @@ this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); Dictionary map = new Dictionary(); map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); map.Add(XmlTag.Metadata1.Tag(), "Data 1"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); ``` @@ -76,13 +78,20 @@ A sale operation which also returns a card token. This functionality is not avai | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp //Initiate a sale for 10.00 in Great British Pounds api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +api.SaleAndTokenizeCard(new BigInteger("1000"), Currency.EUR, map); ``` #### Events invoked @@ -168,13 +177,20 @@ A refund operation moves funds from the merchant account to the cardholder´s cr | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| | `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp //Initiate a refund for 10.00 in Great British Pounds api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +api.Refund(new BigInteger("1000"), Currency.EUR, map); ``` #### Events invoked @@ -259,17 +275,19 @@ Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP | ----------- | ----------- | | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required
*Currency* | Currency of the transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp -// Basic +// Basic MoTo Sale this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); // With options Dictionary dic = new Dictionary(); dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); ``` @@ -305,14 +323,22 @@ A MOTO refund operation moves funds from the merchant account to the cardholder | `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| | `currency` Required*Currency* | Currency of the transaction.| | `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| **Code example** ```csharp +//Basic MoTo Refund this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + +//With Options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +this.Hapi.MotoRefund(new BigInteger("1000"), Currency.EUR, dic); ``` #### Events invoked From 2285ced38d8dd29078c1fd0be14553e291d09b49 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 18 Jan 2024 11:58:03 +0100 Subject: [PATCH 080/115] Add automatic refunds (#104) * Added Automatic Refunds Add: Automatic Refunds Fix: Report Configuration * Update Automatic Partial Refund * Update androidtransactions.md --------- Co-authored-by: Antoine --- android/androiddevicemanagement.md | 5 +- android/androidobjects.md | 5 +- android/androidtransactions.md | 95 +++++++++++++++++++ .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- .../androiddevicemanagement.md | 2 +- .../androidobjects.md | 5 +- 17 files changed, 129 insertions(+), 25 deletions(-) diff --git a/android/androiddevicemanagement.md b/android/androiddevicemanagement.md index bf46b10..d825b7f 100644 --- a/android/androiddevicemanagement.md +++ b/android/androiddevicemanagement.md @@ -154,8 +154,9 @@ Fetches your transactions report from a payment terminal. If you want to print t ```java //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); -terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + api.getTransactionsReport(configuration); ``` diff --git a/android/androidobjects.md b/android/androidobjects.md index 67ba846..4b02e8d 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -897,8 +897,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 3070c67..a78dc19 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -247,6 +247,101 @@ Invoked when the terminal finishes processing the transaction | *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + ## Refund reversal{#6} `refundReversal` diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md index af0bcb8..deabc2d 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md index 28fcfe5..13bf3c4 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidobjects.md @@ -780,8 +780,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md index af0bcb8..deabc2d 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md index 862459a..ba28c0e 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidobjects.md @@ -783,8 +783,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md index 5f0850d..49c7be1 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md index bf42005..ddc2eab 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidobjects.md @@ -779,8 +779,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md index 5f0850d..49c7be1 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md index c867741..8f97c44 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidobjects.md @@ -798,8 +798,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md index d40ca88..70f881c 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md index fb439e2..f5fecbc 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidobjects.md @@ -803,8 +803,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md index 5fb2f97..e786035 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md index 34cc0d8..6a3bd98 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidobjects.md @@ -833,8 +833,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md index bf46b10..e9e3614 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androiddevicemanagement.md @@ -155,7 +155,7 @@ Fetches your transactions report from a payment terminal. If you want to print t //Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: List terminalSerialNumber = new ArrayList<>(); terminalSerialNumber.add("12345"); -ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", terminalSerialNumber); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20210430000000", "20210430235959", "+00:00", terminalSerialNumber); api.getTransactionsReport(configuration); ``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md index 67ba846..4b02e8d 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidobjects.md @@ -897,8 +897,9 @@ An object to store all the configuration for a transactions report. | Parameter | Description | | ----------- | ----------- | | `currency`
[*Currency*](#13) | The currency to filter the transactions| -| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss.| -| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss.| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| | `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| **Code example** From 93509ba2bc7d9f4d2de1da0b41465b3a24442566 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 19 Jan 2024 16:27:44 +0100 Subject: [PATCH 081/115] Add release notes 7.1004.2 (#105) * Added Release Notes 7.1004.2 Android SDK * Added Fix Slovenian formatting currency --- android/androidreleasenotes.md | 19 +++++++++++++++++++ android/androidtransactions.md | 1 + 2 files changed, 20 insertions(+) diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 9e5c2bb..3fba142 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,25 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + ## 7.1004.1 **Features**: diff --git a/android/androidtransactions.md b/android/androidtransactions.md index a78dc19..dab62b1 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -252,6 +252,7 @@ Invoked when the terminal finishes processing the transaction `automaticRefund` A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + **Parameters** From 7eddd98df55011a5af5a887a20ac1f8de400bcd4 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 19 Jan 2024 17:15:05 +0100 Subject: [PATCH 082/115] Add: New version 7.1004.2 Android SDK (#106) --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++++ .../androideventlisteners.md | 731 ++++++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 ++++++++ .../androidintroduction.md | 175 +++ .../androidmigrationguide.md | 265 ++++ .../androidobjects.md | 1215 +++++++++++++++++ .../androidreleasenotes.md | 292 ++++ .../androidtransactions.md | 1125 +++++++++++++++ ...version-Android SDK 7.1004.2-sidebars.json | 8 + android_versions.json | 1 + 12 files changed, 4891 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1004.2/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1004.2-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1004.2/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1004.2/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1004.2/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidobjects.md new file mode 100644 index 0000000..4b02e8d --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidobjects.md @@ -0,0 +1,1215 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md new file mode 100644 index 0000000..3fba142 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md @@ -0,0 +1,292 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.1004.2-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1004.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1004.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index bd1fb02..80a78d8 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1004.2", "Android SDK 7.1004.1", "Android SDK 7.1004.0", "Android SDK 7.1002.0", From 47c5cabd8d9bc5f6f753688db7c8433dcace8032 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 7 Feb 2024 12:17:21 +0100 Subject: [PATCH 083/115] TMS landing page 2024 (Including TMS API docs link) (#108) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs --- src/pages/index.js | 233 ++++++++++++++++++++++++-------------------- static/img/shop.png | Bin 0 -> 9162 bytes 2 files changed, 125 insertions(+), 108 deletions(-) create mode 100644 static/img/shop.png diff --git a/src/pages/index.js b/src/pages/index.js index bae2a87..df88af5 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -6,123 +6,140 @@ import { padding } from "@mui/system"; function Header() { - return ( -
-
-

Developer Center

-
- Logo -

-

Global Payments-Powered Growth for SaaS

-
-
- ); + return ( +
+
+

Developer Center

+
+ Logo +

+

Global Payments-Powered Growth for SaaS

+
+
+ ); } function Options() { - return ( -
-

+ return ( +
+

- + +
-
- - ); + ); } function Main() { - const [count, setCount] = useState(0); + const [count, setCount] = useState(0); - return ( -
-
-
- -
-
- -
-
-
-
- ); + return ( +
+
+
+ +
+
+ +
+
+
+
+ ); } -export default Main; \ No newline at end of file +export default Main; diff --git a/static/img/shop.png b/static/img/shop.png new file mode 100644 index 0000000000000000000000000000000000000000..c1081adcd5dd17743016003e542a66591fa160a7 GIT binary patch literal 9162 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 literal 0 HcmV?d00001 From dd7182bb9b050319ce6b0dbf0141fbb65b2ef69f Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 7 Feb 2024 13:43:35 +0100 Subject: [PATCH 084/115] Updated Docs Links (#109) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Update docusarus.config links --- docusaurus.config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docusaurus.config.js b/docusaurus.config.js index 86ff891..cb64877 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -91,6 +91,14 @@ module.exports = { label: 'Online Payments Docs', href: 'https://developer-ecomm.handpoint.com/cnpdocs/index.html', }, + { + label: 'Transaction Analytics API', + href: 'https://txnfeedapi.handpoint.com/', + }, + { + label: 'Merchants & Terminals Management API', + href: 'https://tmsdoc.handpoint.com/', + }, ], }, { From fee6261442ac4ff66fecab2df1e483dd2750a5d4 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 19 Mar 2024 10:44:44 +0100 Subject: [PATCH 085/115] Changed device name from HiLite Plus to BluePad 50+ (#111) Changed name from HiLite Plus to BluePad 50+ --- src/pages/cpdocs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 5c079cc..341b57e 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -414,7 +414,7 @@ function TableTerminals() {

- HiLite Plus + BluePad 50+

@@ -753,7 +753,7 @@ function CommunicationTypesTable() { - HiLite Plus + BluePad 50+ From dd80f8bf4f55f85afd16cdb1d5f3737983d2ffd4 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 4 Jun 2024 11:01:32 +0200 Subject: [PATCH 086/115] Add sdk 7.1005.0 (#113) * Add 7.1005.0 SDK * updated admonition --- android/androidreleasenotes.md | 11 +++++++++++ src/pages/cpdocs.js | 21 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 3fba142..cfc7bf3 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,17 @@ id: androidreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + ## 7.1004.2 **Features**: diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 341b57e..9d04fb5 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -739,6 +739,7 @@ function CommunicationTypesTable() { Ethernet Cellular Wi-Fi + USB @@ -750,15 +751,17 @@ function CommunicationTypesTable() { + BluePad 50+ - + + @@ -768,6 +771,7 @@ function CommunicationTypesTable() { + @@ -777,6 +781,7 @@ function CommunicationTypesTable() { + @@ -786,6 +791,7 @@ function CommunicationTypesTable() { + @@ -796,6 +802,7 @@ function CommunicationTypesTable() { + @@ -805,6 +812,7 @@ function CommunicationTypesTable() { + @@ -814,6 +822,7 @@ function CommunicationTypesTable() { + @@ -823,6 +832,7 @@ function CommunicationTypesTable() { + @@ -832,6 +842,7 @@ function CommunicationTypesTable() { + @@ -841,6 +852,7 @@ function CommunicationTypesTable() { + @@ -850,6 +862,7 @@ function CommunicationTypesTable() { + @@ -859,6 +872,7 @@ function CommunicationTypesTable() { + @@ -868,6 +882,7 @@ function CommunicationTypesTable() { + @@ -877,6 +892,7 @@ function CommunicationTypesTable() { + @@ -886,6 +902,7 @@ function CommunicationTypesTable() { + @@ -895,6 +912,7 @@ function CommunicationTypesTable() { + @@ -904,6 +922,7 @@ function CommunicationTypesTable() { + From 6725452a690148b3d64ca5d7e601b715c727cbb6 Mon Sep 17 00:00:00 2001 From: Miguel Date: Thu, 6 Jun 2024 16:58:22 +0200 Subject: [PATCH 087/115] Created version Android SDK 7.1005.0 (#114) Created version 7.1005.0 --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++++ .../androideventlisteners.md | 731 ++++++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 567 ++++++++ .../androidintroduction.md | 175 +++ .../androidmigrationguide.md | 265 ++++ .../androidobjects.md | 1215 +++++++++++++++++ .../androidreleasenotes.md | 303 ++++ .../androidtransactions.md | 1125 +++++++++++++++ ...version-Android SDK 7.1005.0-sidebars.json | 8 + android_versions.json | 1 + 12 files changed, 4902 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.0/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1005.0-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1005.0/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1005.0/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1005.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidintegrationguide.md new file mode 100644 index 0000000..1a43b1f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidintegrationguide.md @@ -0,0 +1,567 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidobjects.md new file mode 100644 index 0000000..4b02e8d --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidobjects.md @@ -0,0 +1,1215 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` + +**Code example** + +```java +//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `port` Required
*String* | The port to connect to (optional).| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md new file mode 100644 index 0000000..cfc7bf3 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md @@ -0,0 +1,303 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_sidebars/version-Android SDK 7.1005.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1005.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1005.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 80a78d8..2d0d354 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1005.0", "Android SDK 7.1004.2", "Android SDK 7.1004.1", "Android SDK 7.1004.0", From 71a79cd1a90a17359ca6b2afd993315fc76b5d11 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 10 Jul 2024 19:04:23 +0200 Subject: [PATCH 088/115] Added new code example for USB (#116) --- android/androidintegrationguide.md | 267 ++++++++++++++++++++++++++++- android/androidobjects.md | 17 +- 2 files changed, 275 insertions(+), 9 deletions(-) diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index 1a43b1f..3735367 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -11,6 +11,7 @@ id: androidintegrationguide 1. **[Android Native (PAX/Telpo)](#8)** 2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** ## Android Native Integration (PAX/Telpo) {#8} @@ -564,4 +565,268 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. -Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android/androidobjects.md b/android/androidobjects.md index 4b02e8d..a9bae86 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -265,19 +265,20 @@ An object representing the tokenized card. An enum representing different connection methods with the payment terminal. -Currently `BLUETOOTH` and `ANDROID_PAYMENT` are the only supported types. +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. **Possible values** -`BLUETOOTH` `ANDROID_PAYMENT` +`BLUETOOTH` `ANDROID_PAYMENT` `USB` **Code example** ```java -//Currently BLUETOOTH and ANDROID_PAYMENT are the only connection methods available. +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. public enum ConnectionMethod { - BLUETOOTH, - ANDROID_PAYMENT + BLUETOOTH, + ANDROID_PAYMENT, + USB } ``` @@ -314,14 +315,14 @@ An object to store the information about the payment terminal in use. **Constructor** ```java -Device( String name , String address , String port , ConnectionMethod connectionMethod , String sharedSecret , int timeout ); +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); ``` | Parameter | Notes | | ----------- | ----------- | | `name` Required
*String* | A name to identify the device| | `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| -| `port` Required
*String* | The port to connect to (optional).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| | `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| | `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| | `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| @@ -341,7 +342,7 @@ Device( String name , String address , String port , ConnectionMethod connection Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); //Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection -Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "", ConnectionMethod.ANDROID_PAYMENT); +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); ``` ## Device Capabilities{#24} From 4a03afbf7f0a1cd875132c8c837f7d1c6e1d36ce Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 21 Aug 2024 13:19:22 +0200 Subject: [PATCH 089/115] New GTS endpoint added (#117) --- restapi/restendpoints.md | 60 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.20.0/restdownloads.md | 10 + .../version-REST API 2.20.0/restendpoints.md | 481 ++++++++++ .../restintroduction.md | 55 ++ .../version-REST API 2.20.0/restobjects.md | 840 ++++++++++++++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 93 ++ .../version-REST API 2.20.0/restsandbox.md | 44 + .../version-REST API 2.20.0-sidebars.json | 8 + restapi_versions.json | 1 + 11 files changed, 1611 insertions(+), 3 deletions(-) create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.20.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.20.0-sidebars.json diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index fae9914..d9dfd31 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -334,11 +334,11 @@ Error example response (using invalid guid): ## /transactions/{transactionReference}/status :::warning -This endpoint does not use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** ::: -The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the current status of a transaction based on its unique reference. It accepts the transaction reference as a path parameter and returns the current status of the transaction in the response. The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: @@ -357,7 +357,7 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | | `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | -**Returns** +**Responses** | Response | Response Code | | ----------- | ----------- | @@ -425,3 +425,57 @@ RESPONSE: } ``` +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ----------- | ----------- | +| all |Returns the status of all transactions associated with the given `transactionReference`. | +| {index} |Returns the status of a specific transaction identified by its index in the sequence of transactions associated with the `transactionReference`. The index is a 1-based integer, where 1 represents the first transaction, 2 the second, and so on.| + +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.20.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.20.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md new file mode 100644 index 0000000..5ce5eb3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md new file mode 100644 index 0000000..d9dfd31 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md @@ -0,0 +1,481 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "customerReference": "op15248", + "terminal_type": "PAXA920" + } + ] +``` + + + + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ----------- | ----------- | +| all |Returns the status of all transactions associated with the given `transactionReference`. | +| {index} |Returns the status of a specific transaction identified by its index in the sequence of transactions associated with the `transactionReference`. The index is a 1-based integer, where 1 represents the first transaction, 2 the second, and so on.| + +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.20.0/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md new file mode 100644 index 0000000..68af6f1 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md @@ -0,0 +1,840 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + + + + + + + + + + + + + + diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.20.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md new file mode 100644 index 0000000..157064c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -0,0 +1,93 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.20.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.20.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.20.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.20.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.20.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index c006714..430ff18 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.20.0", "REST API 2.17.0", "REST API 2.15.0", "REST API 2.14.0", From 8d46f1caf4f3d3e3c918ce96affdaf04f98c7334 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 14 Feb 2025 10:57:39 -0500 Subject: [PATCH 090/115] Removing HiPro, adding IM25 (#118) --- docusaurus.config.js | 9 ++- src/pages/cpdocs.js | 189 +++++++++++++++++-------------------------- src/pages/index.js | 4 +- 3 files changed, 82 insertions(+), 120 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index cb64877..e788345 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -36,6 +36,10 @@ module.exports = { type: 'docsVersionDropdown', docsPluginId: 'android', }, + { + type: 'docsVersionDropdown', + docsPluginId: 'restapi', + }, { type: 'docsVersionDropdown', docsPluginId: 'ios', @@ -50,10 +54,7 @@ module.exports = { docsPluginId: 'javascript', activeBaseRegex: 'javascript_versioned_docs/' }, - { - type: 'docsVersionDropdown', - docsPluginId: 'restapi', - }, + { type: 'docsVersionDropdown', docsPluginId: 'express', diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 9d04fb5..63e7cb8 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -159,18 +159,6 @@ function SdkTerminalTable() { - - HiPro - - - - - - - - - - PAX Android Terminals @@ -261,24 +249,6 @@ function IntegrationPaths() {
-

-
-
-
-
-

- Lightning Integration -

-

The Handpoint HiPro is an all-in-one payment terminal compatible with iOS devices. The lightning port is used for the communication - between the iOS phone or ipod and the payment terminal. This is the perfect line buster for busy retail environments. With its integrated scanner It can also be used to - scan barcodes and manage inventory as well as taking payments on the spot, directly in the store aisles.

-
- HiPro integration -
-
-
-
-
); @@ -392,7 +362,7 @@ function TableTerminals() {
-
+
@@ -409,7 +379,7 @@ function TableTerminals() {
-
+
@@ -425,23 +395,6 @@ function TableTerminals() {
-
-
-
-
-

- HiPro -

-
- - -
-
-
-
-


@@ -701,17 +654,44 @@ function TableTerminals() {


-
-

- PAX IM30 -

-
- - + +

+
+
+
+
+
+

+ PAX IM25 +

+
+ + +
+
+
+
+
+
+
+
+
+

+ PAX IM30 +

+
+ + +
+
+
+
@@ -734,11 +714,10 @@ function CommunicationTypesTable() { - Lightning - Bluetooth - Ethernet Cellular Wi-Fi + Ethernet + Bluetooth USB @@ -747,182 +726,164 @@ function CommunicationTypesTable() { HiLite - - + BluePad 50+ - - - - - - - - HiPro - - - - + PAX A910S - - - + + PAX A920 - - - + + PAX A920 PRO - - - + + PAX A920 MAX - - - + + PAX A35 - - + PAX A50 - - - + + PAX A60 - - - + + PAX A77 - - - + + PAX A80 - - + PAX A800 - - - + + PAX A960 - - - + + PAX A6650 - - - + + PAX A8700 + + + + + + + PAX IM25 + PAX IM30 - - + Telpo TPS900 - - - + + diff --git a/src/pages/index.js b/src/pages/index.js index df88af5..b03761d 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -55,7 +55,7 @@ function Options() {
-

In-person payments

+

In-person payments

In-person payments
@@ -71,7 +71,7 @@ function Options() {
-

Online payments

+

Online payments (Europe)

Online payments
From 6716db6b09173874a9f8d92af3cd4aa877d3e0bc Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Tue, 4 Mar 2025 10:32:00 +0100 Subject: [PATCH 091/115] EFTCLIENT-5268 Add tokenization operations in the JS SDK (#119) Adding documentation for JavaScript SDK version 7.2.2 --- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 757 +++++++++++++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 +++ .../javascriptreleasenotes.md | 94 +++ .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 262 ++++++ .../javascripttransactiontypes.md | 779 ++++++++++++++++++ ...version-JavaScript SDK 7.2.2-sidebars.json | 8 + javascript_versions.json | 1 + 10 files changed, 2120 insertions(+) create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.2.2-sidebars.json diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptintroduction.md new file mode 100644 index 0000000..baa4147 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md new file mode 100644 index 0000000..061d609 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md @@ -0,0 +1,757 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient.(**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptquickintegration.md new file mode 100644 index 0000000..f5c935d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md new file mode 100644 index 0000000..7d4ca4e --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md @@ -0,0 +1,94 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.2.2 +**Features:** + +A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 7.2.0 +**Features:** + +We're excited to announce the latest update to our JavaScript SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](javascriptobjects.md#money-remittance-options)), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptterminalmanagement.md new file mode 100644 index 0000000..9a7c809 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptterminalmanagement.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascripttransactiontypes.md new file mode 100644 index 0000000..928fddc --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascripttransactiontypes.md @@ -0,0 +1,779 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale ([Tip Configuration](javascriptobjects.md#39), [Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + }, + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale and tokenize ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a MOTO sale (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.2.2-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 275fc24..04d3f90 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.2.2", "JavaScript SDK 7.2.0", "JavaScript SDK 7.1.0", "JavaScript SDK 7.0.0", From 480cc91da143002500f59fb1e9cb19ae4743f4cd Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Wed, 16 Apr 2025 17:09:19 +0200 Subject: [PATCH 092/115] SDK-3815 (#120) * Add tokenize option in Windows SDK docs TODO: link this to the general description of our tokenize feature when ready, which is under development * Adding description of tokenized payments operations as a feature * Adding Android SDK 7.1009.5 version * Adding tokenized payments operations (standalone) * Adding missing Android SDK versions and adding draft of Tokenized Payments Operations overview TODO: complete 7.1009.4 release notes * Adding tokenized payments operations TODO: review text and format * Fixing some formatting * Linking to detailed information on tokenize in JS and Win SDKs * Integrationg Tokenize and Modify in new Tokenized Payments Operations * Removing PLM info that should not be public * Masking info --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 309 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 321 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 327 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 333 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 347 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 353 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 359 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 365 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 379 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 385 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 395 +++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 401 ++++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 409 ++++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 407 ++++ .../androidtransactions.md | 1125 +++++++++ .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 175 ++ .../androidmigrationguide.md | 265 ++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 432 ++++ .../androidtransactions.md | 2130 +++++++++++++++++ ...version-Android SDK 7.1005.1-sidebars.json | 8 + ...version-Android SDK 7.1005.2-sidebars.json | 8 + ...version-Android SDK 7.1005.3-sidebars.json | 8 + ...version-Android SDK 7.1005.4-sidebars.json | 8 + ...version-Android SDK 7.1006.0-sidebars.json | 8 + ...version-Android SDK 7.1006.1-sidebars.json | 8 + ...version-Android SDK 7.1006.2-sidebars.json | 8 + ...version-Android SDK 7.1006.3-sidebars.json | 8 + ...version-Android SDK 7.1008.0-sidebars.json | 8 + ...version-Android SDK 7.1008.1-sidebars.json | 8 + ...version-Android SDK 7.1008.3-sidebars.json | 8 + ...version-Android SDK 7.1008.4-sidebars.json | 8 + ...version-Android SDK 7.1008.5-sidebars.json | 8 + ...version-Android SDK 7.1008.6-sidebars.json | 8 + ...version-Android SDK 7.1009.0-sidebars.json | 8 + ...version-Android SDK 7.1009.1-sidebars.json | 8 + ...version-Android SDK 7.1009.4-sidebars.json | 8 + ...version-Android SDK 7.1009.5-sidebars.json | 8 + android_versions.json | 15 + .../javascriptobjects.md | 4 +- .../javascriptreleasenotes.md | 2 +- src/pages/cpdocs.js | 8 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 361 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 ++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 618 +++++ .../windowsreleasenotes.md | 108 + .../windowstransactions.md | 938 ++++++++ .../version-Windows SDK 4.3.1-sidebars.json | 8 + windows_versions.json | 1 + 183 files changed, 83953 insertions(+), 7 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.1/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.2/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.3/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1005.4/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.0/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.1/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.2/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1006.3/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.0/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1005.1-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1005.2-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1005.3-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1005.4-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1006.0-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1006.1-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1006.2-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1006.3-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.0-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.1-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.3-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.4-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.5-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1008.6-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1009.0-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1009.1-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1009.4-sidebars.json create mode 100644 android_versioned_sidebars/version-Android SDK 7.1009.5-sidebars.json create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.3.1/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.3.1-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1005.1/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1005.1/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1005.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md new file mode 100644 index 0000000..5ff5102 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md @@ -0,0 +1,309 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1005.2/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1005.2/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1005.2/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md new file mode 100644 index 0000000..fa68e44 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md @@ -0,0 +1,321 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1005.3/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1005.3/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1005.3/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md new file mode 100644 index 0000000..bd7e148 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md @@ -0,0 +1,327 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1005.4/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1005.4/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1005.4/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md new file mode 100644 index 0000000..74a2b1a --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md @@ -0,0 +1,333 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1006.0/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1006.0/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1006.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md new file mode 100644 index 0000000..605af7e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md @@ -0,0 +1,347 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1006.1/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1006.1/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1006.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md new file mode 100644 index 0000000..45ba8b7 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md @@ -0,0 +1,353 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1006.2/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1006.2/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1006.2/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md new file mode 100644 index 0000000..be0aa98 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md @@ -0,0 +1,359 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1006.3/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1006.3/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1006.3/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md new file mode 100644 index 0000000..d5b4e65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md @@ -0,0 +1,365 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.0/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.0/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.0/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md new file mode 100644 index 0000000..7a1ed1a --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md @@ -0,0 +1,379 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.1/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.1/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md new file mode 100644 index 0000000..32b7f52 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md @@ -0,0 +1,385 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.3/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.3/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.3/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md new file mode 100644 index 0000000..23a1c33 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md @@ -0,0 +1,395 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.4/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.4/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.4/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md new file mode 100644 index 0000000..5e29908 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md @@ -0,0 +1,401 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.5/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.5/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.5/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md new file mode 100644 index 0000000..0446288 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md @@ -0,0 +1,409 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.5 +**Fixes**: + +- The was an error in Interac Debit sales where a duplicate 'Checking/Savings' prompt was leading to decline the transaction. This issue has been addressed. + +- When initiating duplicate sales within a short timeframe, the second sale was being rejected with a "Device Busy, FAILED" error, while the first sale was being successfully approved on the terminal. This incorrect behavior has been corrected + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1008.6/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1008.6/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1008.6/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidobjects.md new file mode 100644 index 0000000..a9bae86 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md new file mode 100644 index 0000000..372986e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md @@ -0,0 +1,407 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md new file mode 100644 index 0000000..dab62b1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md @@ -0,0 +1,1125 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Tokenize And Modify +`tokenizedOperation` + +A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| +| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| +| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| + +```java +//Tokenize a card and modifies the amount of a sale operation. +//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. +//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. +//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. + +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setMetadata(metadata); + +api.tokenizedOperation(Currency.GBP,options); + +// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. +class LoyaltyEngine : Events.CardTokenization { + + override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { + // Call the loyalty engine and apply discounts based on cardTokenizationData + val finalAmount: BigInteger = ... // Calculate the final amount with discounts + // Call resume to continue the sale operation + val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) + // Resume the operation using the callback + callback.resume(sale) + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. +//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. +//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. + +Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); + +RefundOptions refundOptions = new RefundOptions(); +refundOptions.setMetadata(metadataRefund); +OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); + +api.tokenizedOperation(Currency.GBP,operation,options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**cardTokenization**](androideventlisteners.md#card-tokenization) + +Invoked when the terminal finishes processing the transaction. + +*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1009.5/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1009.5/androideventlisteners.md new file mode 100644 index 0000000..dd79145 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1009.5/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidintegrationguide.md new file mode 100644 index 0000000..3735367 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md new file mode 100644 index 0000000..d9cf12b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md @@ -0,0 +1,175 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ + + +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidmigrationguide.md new file mode 100644 index 0000000..47511b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidobjects.md new file mode 100644 index 0000000..2ca3c4a --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md new file mode 100644 index 0000000..b8ac730 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md @@ -0,0 +1,432 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting two new PAX card readers models: **IM25** and **A8900**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- The "kiosk mode" command has been renamed to "unattended mode" + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md new file mode 100644 index 0000000..c4658b2 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md @@ -0,0 +1,2130 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +```mermaid +sequenceDiagram + participant Integrator + participant SDK + participant Cardholder + + Integrator ->> SDK: tokenizedOperation(amount, currency, options) + Cardholder ->> SDK: Presents Card + SDK ->> Integrator: Events.CardTokenized (CardTokenizationData + ResumeCallback) + Integrator ->> SDK: resume(SaleOperationDto) + alt Sale Operation + SDK ->> Card Network: Process Sale + SDK -->> Integrator: Events.EndOfTransaction (Result) + else Unsupported Operation + SDK -->> Integrator: MessageType.FEATURE_NOT_SUPPORTED + end +``` + +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +```mermaid +sequenceDiagram + participant Integrator + participant SDK + participant Cardholder + participant REST API + + Integrator ->> SDK: tokenizedOperation(currency, operation, options) + Cardholder ->> SDK: Presents Card + SDK ->> REST API: Request Card Token + REST API -->> SDK: Card Token + SDK ->> Card Network: Execute Provided Operation (Refund, SaleReversal, RefundReversal) + SDK -->> Integrator: Events.EndOfTransaction (Result) +``` + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `isTokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `isTokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `isTokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `isTokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "isTokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram (Mermaid)** + +```mermaid +sequenceDiagram + participant CloudService + participant SDK + participant Cardholder + participant REST API + + CloudService ->> SDK: CloudFinancialRequest (operation=Sale, isTokenize=true) + Cardholder ->> SDK: Presents Card + SDK ->> REST API: Tokenize Card + REST API -->> SDK: Card Token + SDK ->> Integrator: Events.CardTokenized + Integrator ->> SDK: resume(Sale) + SDK ->> Card Network: Execute Sale + SDK -->> Integrator: Events.EndOfTransaction +``` + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `isTokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `isTokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram (Mermaid)** + +```mermaid +sequenceDiagram + participant CloudService + participant SDK + participant Integrator + + CloudService ->> SDK: CloudFinancialRequest (operation=SaleReversal, isTokenize=true) + SDK ->> Integrator: Events.DependantReversalReceived + alt executeDependantOperation + Integrator ->> SDK: executeDependantOperation() + SDK ->> Card Network: Execute SaleReversal + SDK -->> Integrator: Events.EndOfTransaction + else finishWithoutCardOperation + Integrator ->> SDK: finishWithoutCardOperation() + SDK -->> Integrator: Txn Result (Authorised, no money moved) + else cancel + Integrator ->> SDK: cancel() + SDK -->> Integrator: Txn Result (Cancelled) + end +``` + +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `isTokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `isTokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram (Mermaid)** + +```mermaid +sequenceDiagram + participant CloudService + participant SDK + participant Integrator + + CloudService ->> SDK: CloudFinancialRequest (operation=Refund, isTokenize=true) + SDK ->> Integrator: Events.DependantRefundReceived + alt executeDependantOperation + Integrator ->> SDK: executeDependantOperation() + SDK ->> Card Network: Execute Refund + SDK -->> Integrator: Events.EndOfTransaction + else finishWithoutCardOperation + Integrator ->> SDK: finishWithoutCardOperation() + SDK -->> Integrator: Txn Result (Authorised, no money moved) + else cancel + Integrator ->> SDK: cancel() + SDK -->> Integrator: Txn Result (Cancelled) + end +``` + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `isTokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `isTokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `isTokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram (Mermaid)** + +```mermaid +sequenceDiagram + participant CloudService + participant SDK + participant Integrator + + CloudService ->> SDK: CloudFinancialRequest (operation=RefundReversal, isTokenize=true) + SDK ->> Integrator: Events.DependantReversalReceived + alt executeDependantOperation + Integrator ->> SDK: executeDependantOperation() + SDK ->> Card Network: Execute RefundReversal + SDK -->> Integrator: Events.EndOfTransaction + else finishWithoutCardOperation + Integrator ->> SDK: finishWithoutCardOperation() + SDK -->> Integrator: Txn Result (Authorised, no money moved) + else cancel + Integrator ->> SDK: cancel() + SDK -->> Integrator: Txn Result (Cancelled) + end +``` + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1005.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1005.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1005.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1005.2-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1005.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1005.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1005.3-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1005.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1005.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1005.4-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1005.4-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1005.4-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1006.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1006.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1006.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1006.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1006.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1006.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1006.2-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1006.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1006.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1006.3-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1006.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1006.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.3-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.4-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.4-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.4-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.5-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.5-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.5-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1008.6-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1008.6-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1008.6-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1009.0-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1009.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1009.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1009.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1009.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1009.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1009.4-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1009.4-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1009.4-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versioned_sidebars/version-Android SDK 7.1009.5-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1009.5-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1009.5-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 2d0d354..044037b 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,19 @@ [ + "Android SDK 7.1009.5", + "Android SDK 7.1008.6", + "Android SDK 7.1008.5", + "Android SDK 7.1008.4", + "Android SDK 7.1008.3", + "Android SDK 7.1008.1", + "Android SDK 7.1008.0", + "Android SDK 7.1006.3", + "Android SDK 7.1006.2", + "Android SDK 7.1006.1", + "Android SDK 7.1006.0", + "Android SDK 7.1005.4", + "Android SDK 7.1005.3", + "Android SDK 7.1005.2", + "Android SDK 7.1005.1", "Android SDK 7.1005.0", "Android SDK 7.1004.2", "Android SDK 7.1004.1", diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md index 061d609..58bed4b 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md @@ -399,7 +399,7 @@ An object to store the customization options for a refund. This object can be em | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| @@ -461,7 +461,7 @@ An object to store the customization options for a sale operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow.| +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md index 7d4ca4e..9fbb952 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md @@ -12,7 +12,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.2.2 **Features:** -A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). +A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 7.2.0 **Features:** diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 63e7cb8..0c87ca9 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -1233,13 +1233,12 @@ function HighLevelFeatures() {
-

Tokenize & Modify

+

Tokenized Payments Operations (formerly Tokenize and Modify)

- A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and - modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an - instant discount at the point of sale for loyal customers. + Tokenized payments operations enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. + This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. There are two main modes for how this works, depending on your integration needs: Standalone and Cloud.

@@ -1591,6 +1590,7 @@ function HighLevelFeatures() {
+

); diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsdevicemanagement.md new file mode 100644 index 0000000..99af86d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsdevicemanagement.md @@ -0,0 +1,361 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.Connect(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.Connect(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsevents.md new file mode 100644 index 0000000..e2e35fe --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintegrationguide.md new file mode 100644 index 0000000..1ff930d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + // Put the name of your device + + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md new file mode 100644 index 0000000..d3bb09d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md @@ -0,0 +1,618 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](windowstransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemitanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```csharp +Dictionary map = new Dictionary(); + +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +``` + + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| + + +## Optional Transaction Parameters{#3} + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`tokenize`
*String*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](windowsobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Terminal Parameters + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + + +## Verification Method{#29} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md new file mode 100644 index 0000000..fcc830e --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md @@ -0,0 +1,108 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.3.1 +**Features:** +A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md#3). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 4.2.0 +**Features:** + +We're excited to announce the latest update to our Windows SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](windowsobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is only available for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 4.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](windowstransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](windowstransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](windowstransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowstransactions.md new file mode 100644 index 0000000..c013743 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowstransactions.md @@ -0,0 +1,938 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.SaleAndTokenizeCard(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.Refund(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +// Basic MoTo Sale +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Basic MoTo Refund +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + + +//With Options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.MotoRefund(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +|`currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic PreAuth Increase +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); + +// Basic PreAuth Decrease +this.Hapi.PreAuthorizationIncrease(new BigInteger("-1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will released the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](windowstransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_sidebars/version-Windows SDK 4.3.1-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.3.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.3.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 05d3885..7b8e0b2 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.3.1", "Windows SDK 4.2.0", "Windows SDK 4.1.0", "Windows SDK 4.0.0", From 51c2fefcd03c705ed5105ca5e5fee2c729bf1332 Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Fri, 25 Apr 2025 12:46:57 +0200 Subject: [PATCH 093/115] REST API and SDK updates (#121) * REST API and SDK updates Updating RestAPI endpoints: Added commands, small fixes Updating SDK versions -> removed maven repository and indicate Nexus for both dev and prod SDK versions. Removed A8900 from release notes. converted mermaid to PNG diagrams due to docusaurus v2.1.0 limitations * corrected links for restobjects.md changed restobjects.md to restobjects, looks like the build test doesn't like it in github although it does run locally * corrected typo on link causing broken link --- android/androidintroduction.md | 4 +- .../androidintroduction.md | 6 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 2 - .../androidintroduction.md | 5 +- .../androidreleasenotes.md | 4 +- .../androidtransactions.md | 153 ++------- restapi/restdownloads.md | 2 +- restapi/restreleasenotes.md | 2 +- .../version-REST API 2.14.0/restdownloads.md | 2 +- .../version-REST API 2.15.0/restdownloads.md | 2 +- .../restreleasenotes.md | 2 +- .../version-REST API 2.17.0/restdownloads.md | 2 +- .../restreleasenotes.md | 2 +- .../version-REST API 2.20.0/restdownloads.md | 2 +- .../version-REST API 2.20.0/restendpoints.md | 296 +++++++++++++++++- .../version-REST API 2.20.0/restobjects.md | 23 +- .../restreleasenotes.md | 10 +- src/pages/cpdocs.js | 4 +- static/img/cloud_tokenized_Refund.png | Bin 0 -> 145717 bytes static/img/cloud_tokenized_Sale.png | Bin 0 -> 91970 bytes static/img/cloud_tokenized_SaleReversal.png | Bin 0 -> 152241 bytes .../img/cloud_tokenized_refund_Reversal.png | Bin 0 -> 150862 bytes ...ndalone_Tokenized_Refund_and_reversals.png | Bin 0 -> 108857 bytes static/img/standalone_tokenized_SALE.png | Bin 0 -> 129968 bytes 60 files changed, 390 insertions(+), 286 deletions(-) create mode 100644 static/img/cloud_tokenized_Refund.png create mode 100644 static/img/cloud_tokenized_Sale.png create mode 100644 static/img/cloud_tokenized_SaleReversal.png create mode 100644 static/img/cloud_tokenized_refund_Reversal.png create mode 100644 static/img/standalone_Tokenized_Refund_and_reversals.png create mode 100644 static/img/standalone_tokenized_SALE.png diff --git a/android/androidintroduction.md b/android/androidintroduction.md index d9cf12b..360e509 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -19,7 +19,9 @@ id: androidintroduction
diff --git a/android_versioned_docs/version-Android SDK 6.6.7/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.6.7/androidintroduction.md index b88554e..0fa5842 100644 --- a/android_versioned_docs/version-Android SDK 6.6.7/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.6.7/androidintroduction.md @@ -12,15 +12,13 @@ id: androidintroduction

Android SDK

-

version 6.6.0

- -
diff --git a/android_versioned_docs/version-Android SDK 6.7.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.0/androidintroduction.md index 8473549..c07e88d 100644 --- a/android_versioned_docs/version-Android SDK 6.7.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md index 8182605..d4992f0 100644 --- a/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.2/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 6.7.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.3/androidintroduction.md index 027d8af..f0fe6b7 100644 --- a/android_versioned_docs/version-Android SDK 6.7.3/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.3/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md index 25898c4..7e6e74c 100644 --- a/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 6.7.4/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md index 2e65dd6..b9b4dff 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md index ffeb184..ecfbf23 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md index 8b0658d..1554828 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md index 605af7e..50601bd 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md @@ -14,8 +14,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md index 45ba8b7..219e0bb 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md @@ -20,8 +20,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md index be0aa98..84e0d9d 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md @@ -26,8 +26,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md index d5b4e65..8d9b882 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md @@ -32,8 +32,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md index 7a1ed1a..aac119d 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md @@ -46,8 +46,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md index 32b7f52..68cea4a 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md @@ -52,8 +52,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md index 23a1c33..06b3eff 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md @@ -62,8 +62,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md index 5e29908..174f082 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md @@ -68,8 +68,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md index 0446288..415e4c0 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md @@ -76,8 +76,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md index 372986e..c06a693 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md @@ -74,8 +74,6 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md index d9cf12b..0445acb 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md @@ -14,12 +14,11 @@ id: androidintroduction

Android SDK

- -
diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md index b8ac730..e1e92fd 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md @@ -14,7 +14,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 7.1009.5 **Features**: -We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting two new PAX card readers models: **IM25** and **A8900**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. **Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. @@ -99,8 +99,6 @@ There are two main modes for how this works, depending on integration needs: Sta ## 7.1006.0 **Features**: -- The "kiosk mode" command has been renamed to "unattended mode" - - Now just "CARD" in shown in receipts when the card brand is not in the language library **Fixes**: diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md index c4658b2..59744d3 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md @@ -1191,24 +1191,7 @@ A sealed class representing supported transaction types after tokenization. ** Sequence Diagram ** -```mermaid -sequenceDiagram - participant Integrator - participant SDK - participant Cardholder - - Integrator ->> SDK: tokenizedOperation(amount, currency, options) - Cardholder ->> SDK: Presents Card - SDK ->> Integrator: Events.CardTokenized (CardTokenizationData + ResumeCallback) - Integrator ->> SDK: resume(SaleOperationDto) - alt Sale Operation - SDK ->> Card Network: Process Sale - SDK -->> Integrator: Events.EndOfTransaction (Result) - else Unsupported Operation - SDK -->> Integrator: MessageType.FEATURE_NOT_SUPPORTED - end -``` - +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) --- ** Summary ** @@ -1334,20 +1317,7 @@ The method itself returns `false` if the command fails to send to the device. Ot ** Sequence Diagram ** -```mermaid -sequenceDiagram - participant Integrator - participant SDK - participant Cardholder - participant REST API - - Integrator ->> SDK: tokenizedOperation(currency, operation, options) - Cardholder ->> SDK: Presents Card - SDK ->> REST API: Request Card Token - REST API -->> SDK: Card Token - SDK ->> Card Network: Execute Provided Operation (Refund, SaleReversal, RefundReversal) - SDK -->> Integrator: Events.EndOfTransaction (Result) -``` +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) --- @@ -1521,7 +1491,7 @@ The **Cloud Tokenized Operation** enables remote-triggered financial operations, This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: 1. Parses and validates the `CloudFinancialRequest`. -2. Tokenizes the card (if `isTokenize` is `true` and `operation` is `Sale`). +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). 3. Triggers the **`Events.CardTokenized`** event with token and callback. 4. Proceeds with the Sale operation upon `resume()` call. 5. Emits the final result via **`Events.EndOfTransaction`**. @@ -1539,7 +1509,7 @@ A data object that represents the request payload for initiating cloud-based fin | Field | Type | Description | |--------------------------|-----------------------------------|-------------| | `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | -| `isTokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | | `amount` | `String?` | Transaction amount as string. | | `currency` | `String?` | Currency code. | | `callbackUrl` | `String?` | If present, indicates REST API request. | @@ -1560,7 +1530,7 @@ A data object that represents the request payload for initiating cloud-based fin - The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. - If `callbackUrl` is present, the request is treated as a REST API request. -- If `isTokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. - After receiving the `resume()` call, the SDK performs the Sale operation. --- @@ -1584,7 +1554,7 @@ Emitted after the sale is completed. - The only supported operation for this flow is **Sale**. - Must set: - `operation = Operations.Sale` - - `isTokenize = true` + - `tokenize = true` - Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. --- @@ -1594,7 +1564,7 @@ Emitted after the sale is completed. ```json { "operation": "Sale", - "isTokenize": true, + "tokenize": true, "amount": "1000", "currency": "EUR", "transactionReference": "a1b2c3d4", @@ -1622,24 +1592,9 @@ override fun onCardTokenized( --- -**Sequence Diagram (Mermaid)** - -```mermaid -sequenceDiagram - participant CloudService - participant SDK - participant Cardholder - participant REST API - - CloudService ->> SDK: CloudFinancialRequest (operation=Sale, isTokenize=true) - Cardholder ->> SDK: Presents Card - SDK ->> REST API: Tokenize Card - REST API -->> SDK: Card Token - SDK ->> Integrator: Events.CardTokenized - Integrator ->> SDK: resume(Sale) - SDK ->> Card Network: Execute Sale - SDK -->> Integrator: Events.EndOfTransaction -``` +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) --- @@ -1659,7 +1614,7 @@ The **Sale Reversal Tokenized Operation** is a cloud-initiated process that toke It is identified by: - `operation = Operations.SaleReversal` -- `isTokenize = true` +- `tokenize = true` Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. @@ -1672,7 +1627,7 @@ Upon receiving this request, the SDK emits the **`Events.DependantReversalReceiv | Field | Value | Description | |------------------|----------------------------------|---------------------------------------------| | `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | -| `isTokenize` | `true` | Triggers tokenization before the operation. | +| `tokenize` | `true` | Triggers tokenization before the operation. | Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. @@ -1782,29 +1737,9 @@ class ResumeDependantSaleReversalExecutorImpl( --- -**Sequence Diagram (Mermaid)** - -```mermaid -sequenceDiagram - participant CloudService - participant SDK - participant Integrator - - CloudService ->> SDK: CloudFinancialRequest (operation=SaleReversal, isTokenize=true) - SDK ->> Integrator: Events.DependantReversalReceived - alt executeDependantOperation - Integrator ->> SDK: executeDependantOperation() - SDK ->> Card Network: Execute SaleReversal - SDK -->> Integrator: Events.EndOfTransaction - else finishWithoutCardOperation - Integrator ->> SDK: finishWithoutCardOperation() - SDK -->> Integrator: Txn Result (Authorised, no money moved) - else cancel - Integrator ->> SDK: cancel() - SDK -->> Integrator: Txn Result (Cancelled) - end -``` +**Sequence Diagram** +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) --- **Summary** @@ -1822,7 +1757,7 @@ The **Refund Tokenized Operation** is a cloud-based flow that allows merchants t This operation is identified by: - `operation = Operations.Refund` -- `isTokenize = true` +- `tokenize = true` Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. @@ -1835,7 +1770,7 @@ Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived` | Field | Value | Description | |------------------|------------------------------|-----------------------------------------| | `operation` | `Operations.Refund` | Indicates the refund operation. | -| `isTokenize` | `true` | Enables card tokenization. | +| `tokenize` | `true` | Enables card tokenization. | Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. @@ -1938,28 +1873,9 @@ class ResumeDependantRefundExecutorImpl( --- -**Sequence Diagram (Mermaid)** - -```mermaid -sequenceDiagram - participant CloudService - participant SDK - participant Integrator - - CloudService ->> SDK: CloudFinancialRequest (operation=Refund, isTokenize=true) - SDK ->> Integrator: Events.DependantRefundReceived - alt executeDependantOperation - Integrator ->> SDK: executeDependantOperation() - SDK ->> Card Network: Execute Refund - SDK -->> Integrator: Events.EndOfTransaction - else finishWithoutCardOperation - Integrator ->> SDK: finishWithoutCardOperation() - SDK -->> Integrator: Txn Result (Authorised, no money moved) - else cancel - Integrator ->> SDK: cancel() - SDK -->> Integrator: Txn Result (Cancelled) - end -``` +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) --- @@ -1967,7 +1883,7 @@ sequenceDiagram The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. -- Triggered via `CloudFinancialRequest` with `operation = Refund` and `isTokenize = true`. +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. - Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. - Provides flexibility to execute, authorize without refund, or cancel the transaction. @@ -1981,7 +1897,7 @@ The **Refund Tokenized Operation** is a controlled cloud-based refund workflow t The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: - `operation = Operations.RefundReversal` -- `isTokenize = true` +- `tokenize = true` After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. @@ -1994,7 +1910,7 @@ After receiving the request, the SDK emits the **`Events.DependantReversalReceiv | Field | Value | Description | |------------------|-----------------------------------|----------------------------------------------| | `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | -| `isTokenize` | `true` | Enables card tokenization. | +| `tokenize` | `true` | Enables card tokenization. | Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. @@ -2094,28 +2010,9 @@ class ResumeDependantRefundReversalExecutorImpl( --- -**Sequence Diagram (Mermaid)** - -```mermaid -sequenceDiagram - participant CloudService - participant SDK - participant Integrator - - CloudService ->> SDK: CloudFinancialRequest (operation=RefundReversal, isTokenize=true) - SDK ->> Integrator: Events.DependantReversalReceived - alt executeDependantOperation - Integrator ->> SDK: executeDependantOperation() - SDK ->> Card Network: Execute RefundReversal - SDK -->> Integrator: Events.EndOfTransaction - else finishWithoutCardOperation - Integrator ->> SDK: finishWithoutCardOperation() - SDK -->> Integrator: Txn Result (Authorised, no money moved) - else cancel - Integrator ->> SDK: cancel() - SDK -->> Integrator: Txn Result (Cancelled) - end -``` +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) --- diff --git a/restapi/restdownloads.md b/restapi/restdownloads.md index 5ce5eb3..653b02c 100644 --- a/restapi/restdownloads.md +++ b/restapi/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 157064c..1224d76 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -22,7 +22,7 @@ The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reve ## 2.15.0 **Features:** -We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md index fe7a3ba..fda44c0 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restdownloads.md @@ -5,7 +5,7 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/HandpointAPIRESTCollection.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md index 1ff98d8..65414f0 100644 --- a/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.15.0/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/Handpoint_API_REST_Sept2023.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md index 3a58e6a..7a45b5b 100644 --- a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md @@ -13,7 +13,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 2.15.0 **Features:** -We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md index 5ce5eb3..653b02c 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md index a58bc3a..532b68c 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md @@ -21,7 +21,7 @@ The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reve ## 2.15.0 **Features:** -We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md index 5ce5eb3..653b02c 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restdownloads.md @@ -5,6 +5,6 @@ id: restapidownloads # POSTMAN Collection -Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects.md#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). [Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md index d9dfd31..baff356 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md @@ -22,7 +22,7 @@ Initializes the REST API client and returns the list of payment terminals associ | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | Returns @@ -51,14 +51,15 @@ RESPONSE: { "merchant_id_alpha": "merchantID", "serial_number": "082104578", - "customerReference": "op15248", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", "terminal_type": "PAXA920" } ] ``` - - +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: @@ -76,7 +77,7 @@ POST endpoint used to send a financial operation to the payment terminal. The tr | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | @@ -92,6 +93,9 @@ POST endpoint used to send a financial operation to the payment terminal. The tr **Code Example** +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: ```shell Operation executed using CLI tool CURL: @@ -164,7 +168,7 @@ GET endpoint used to retrieve transaction results from the payment terminal. In | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | @@ -270,7 +274,7 @@ Note: If two tip adjustments are sent for the same original transaction, only th | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | | `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | @@ -354,8 +358,13 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: **Responses** @@ -436,21 +445,30 @@ The `https://transactions.handpoint.io/transactions/{transactionReference}/statu **Selector Values** | Selector | Description | -| ----------- | ----------- | -| all |Returns the status of all transactions associated with the given `transactionReference`. | -| {index} |Returns the status of a specific transaction identified by its index in the sequence of transactions associated with the `transactionReference`. The index is a 1-based integer, where 1 represents the first transaction, 2 the second, and so on.| +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + +:::caution **Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: **Parameters** | Parameter | Description | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| | `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: **Responses** @@ -478,4 +496,252 @@ The `https://transactions.handpoint.io/transactions/{transactionReference}/statu curl -X GET \ -H "ApiKeyCloud: your-api-key" \ "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" - ``` \ No newline at end of file + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payment App needs to be set to **Integrated Mode.**
+Otherwise the response might be a **202 Accepted**, but the command will **not** be executed by the App.
+As a workaround you can use the [`pingDevice` operation](restobjects#operation-types-description) +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md index 68af6f1..1ed8d94 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md @@ -15,7 +15,7 @@ An enum representing the supported acquirers for merchant authentication. **Possible values** -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` +`AMEX` `TEYA|BORGUN` `OMNIPAY` `POSTBRIDGE` `TNS` `TSYS` `VANTIV|WORLDPAY` `SANDBOX` `TILLED` ## Balance @@ -317,7 +317,7 @@ An enum representing different types of operations. Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` @@ -335,9 +335,8 @@ Possible Values: | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | -| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | -| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | | `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | | `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | @@ -822,19 +821,3 @@ An enum representing the possible verification methods used during the transacti Possible values: `UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - - - - - - - - - - - - - - - - diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md index 157064c..62ff25c 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -9,6 +9,14 @@ id: restreleasenotes Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! ::: +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" + + ## 2.17.0 **Features:** @@ -22,7 +30,7 @@ The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reve ## 2.15.0 **Features:** -We are introducing a new transaction type called [Pre-Authorization](restobjects.md#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 0c87ca9..297c73e 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -653,7 +653,7 @@ function TableTerminals() {

-
+

@@ -693,7 +693,7 @@ function TableTerminals() {
- + diff --git a/static/img/cloud_tokenized_Refund.png b/static/img/cloud_tokenized_Refund.png new file mode 100644 index 0000000000000000000000000000000000000000..937ebd9d5a7551954a4fcaad09b4d1d21e962919 GIT binary patch literal 145717 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 h7Q+9F5O{N|S&owKRXf8l$*({lDYOd&* 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 Ioc9+X_=i%=S6$&!$cwF^(j{8!&qyH`Z2#{F zvOP5bMwxs5b1=%krdIq%g}-865wb(DAok6t?I8vu^gHMmY(=aepyg~NTQi|W-V9NhtLOo6T&SMB5x3!^$lfQ4R{HUeK=9I$k_n9=cS!RiOg21@;bqWFOm*+Lllw{@Z7_ z7#fSuZ^yYY^MHW!twf}u0S;Fm3#2_iEf0oO<_AOb|BzXgVKJBC*_ZQwK5HIh#93VE zyJa`Fa0r&qzusImSY=_6{Wssa{}3?J1NtKkiXh$2Mj9G9G0%`PX%@lM`w72$XXX{T z>E?497!2OTp|2uz0AU=FXsx-`Njk};HMo8_B1nFv5?!vSnDaBBzhE@^c0;?Qr+1Yv z6R{soGmu1Asujcn_w2B_eEA(nypOE!%i3M}+H2Z+vc1l?)qWBP6dSm??^j#^S)>I( z*et;GAD;FKPYr)dM3h^Mw%qJ^e`(xQkb}I^(68t z?Zo|7q6DQ!sVuj#j-ebR?6VV!_ZF6x!mZrpUxy~bN(b>+3R6i$3krze=(zl^SxZBB z^(${cMGW^?RMs5$EC{EeOn);j2q}IKH{~K7N!5Ktp(2)6MWi0UZ6NYnQpPCW0eWy3 z(U8(TKqM{T=EfW_WV>NIRfro0fFtd_P52x8{`lvIbpM-TS?~O3e`vqwheS#PU&wug)Pb_pU_}NRd70)TtsY;*;&$g zHox{I936-9bg@(2r;MCO)KEtO zoczp535q5UkOXs2u(p+|3U7l2@COsX)ck3Nw#gsth~Gc3bGX<{$c8|!1~9S*kP|Su z6TlWdm*|ggEJlz<25z(Jm_cH6_Y>T*i*;WIu)d!9U=;EEb#NY-w2~Dz)SQX&PaC(V zxWVb5D?d$+I8B45?^UEkZB*$A=QP`kh780I|8C>24Ofm(yG~^J3%A8o+U$Zd+1p2e ztaz1d@w+npkEgM?$MF?-p7;%*>+gJ=y-{m8emnPY1#2(M@`b*w&k*iGDy7P?1-ZRQocn8OP&rr zvwXQRYO_M=uF#{ZBXMf6F>PN51&0VVcR9zVZyYQj7L|ZeJX>y`laV+S{nQtTh(s0! zbRujKvIaeJyi>97j`*m=gd*#*&Y9AqY0&p;L@ey1E;hc`!Ok%c-NeHP zBoV+HuhE*Eev+)k;{xmnE$-o>Z5SrQysnrK)$dj9hfCW;R$oajLb~8w?iR6KOF)4=N3Yr)$w6liM7<4D2FKbC?>)gUUhtHE(6M~yCbz> zi-kb{k?!02%HH4_D{-A!jve*5W(>USGm=c&`L~87!2-T+{ztXxway;CTZI);SUh@JBFwX7)@&6pk7ukyzytFI$~z(DeD1;*QuCe-pCfVU!q&t4`nA}o%A@N z_p-jIOQ4d5U|MM|Eis*(enkW~Gc|Rb3@BxQn@WgWrw1By&UKluKJO?$6m#SGrBo$_ ze6x%e?^o%#K?glbdhaWRc<8}bA*K8R{PF* zvdS2k^iPyIS#=>x476oU2}o;ow8&!1T01>IRPOpQ&14(Vs(goO@uM8}PD<|gE0ned zx%sBa&`MgbF?r8C$4a8OhUevhLDF-H1M#^18CRKiLD!sTvoHiJeY1;JIRfJQ?1(8g zzig{IlO9bCReh%Crvm40&fm)l8M|NQjg13cVj9vWveK=J=OzcA!X&oO>qN0xhK}D^ z_nU<*$>VOVlcPDJJ|_xrFD|7hI%^*zmwS4Ux zO5B8wQx{A}m!^?Uec|cymW-hhi_3XXsfsHs%5gA!X=n8$c=$|*uPn@4>T=95e{R$T z38I_0EVkgp`E73I$?4)(Yww`ydYY%~&0Oz@;K=)ZQsV|ztDN8E-WOlFIq%8#W=(RQ ze*w{f^F6!Lydym_El$^E{jlL#jPzsx1}y;i-x=?>4X!jK{nCpBnQ;4ME$mKh-&mZ6 z{#<#C@DA1lt|&dG_Bw;gqk)V?)_x`0vXzB(d$#W^V+Uv{9<*v!eyok{uEg3M6=xHE z7IQ_`o=MkEe-%177`#B_Khpv2b68kKj_=V}PhnwEcTW}K z%r)7l>@F|8ZxxNzh;=<=9y^OsukP5$E#TPHp3F8Joj-0N;TXGO3@>Vg6OB~ZwwLFw zi|FBQWfhO0yrGHZUU%LAP9RQAP*^_Z^Nm&n2YbmqIV4P_9DWa_Rg4&G}r=LGI*SS?U?E>CZ<2>%)RUo9?k50FY4*C7DX_ zJz1!vH{ZTv{*Bfz%&mb0u3+%ZE<@SyH+C^n2jA1h#p1^j9=Me>*5aGaY*O4O9aucRhl+Kj%;+?=+R$jb>`eky zI8f@pgsIE*+=5^8P9vX!)$7`uj*;GXv(PzqGM%ja`i`o&?{?EH^sHf&x6muB(pu#X z8R3H;OO@CaXJgP}W3n!d5p?3Og%$k&c(Hebz(f2vFiX0<6~8@SxCQ0sf9(s@%L0dX zsh1yB-#2>2K!EF-s(Xjch%@!s)Xp%OQm)A|xz9$Nwok>V35kTLS`l3G(75Kk@uRB> zjOKx?bjIhj|AArsU3=GUv~Cfy%I70|_L-fZ?i5{bMIVljO3$98%m(&l+vPqlY&@sn!ML*+6d7TeNJE zHk{%3xUn8KHB9d>=E!>=QQu`M%U4;sGSu5DnYk>S zsIw9_UY`&u+9>YzoxmaQlRe9)A&+HMwix%vlN}_GFR70_nlgN^WbeKKx%w}_gnk!A z|LfY%`LTQ-e)E}mm16d0_g=Dh14c;bgY*4oqxg2Y59%|D?d^lRJns*VI?o)DL-DRS zk-t@Sr!@!1I+RHFZGY|jTNP`cAG&o&dwYYOM9d)-a}E`WT`C-Y$M;`za(Z&n;_;T7 zRd3db+tggCiKHpv4e4V#47X{+;z)sl!jVbOXwr(NX*X9_9oOk3FFd1FhK-}X4$cbq z*|-oxWxp_M!+zN(eWdM_J2j~i3hSi>`P(#ozdZ2n);qbA``wgfZl~iHM)xTbo^82j zpB4;T73&5S*XaadlG% zUwWwMrjgbU@FZnEd*_2bF9h)5@wQkNp?zbR?d(41u@C&$+~B=zQe9pB8%3z2xL?d+ zxWKjYT9w>;9J}jSqxr<#ZQ`xw+XO|x1ym7yQ+9Hkci7qBAgG!2_MVU8X>O1VtXYY= za8G%8>SAi$onyvYq(bl5l)%8AGr)t3w2FjmJ%sX~kM|zoF-=<`ks?vt@q~vHKhvEV zM=!ORel)0!gwkYsQ^(V!)bZ4_+^gQFHovs@3SirDdZS+un_{y%f0y=H;W@Tek))EmzFhiO|~foXjVnJybaA5_V7}jdXb0yJ+N?AWf@%56;}SPS%wi zPcv0qm~E*7-md8HD#ns5i1{zc!%{>&5RKz_ncmX+=mmJgl~Dq zJHHWre1e5FdlB+^FcrB4yen9@=V%3B!;#AH#_vvgGF1h3p z&z7AL+qud6W^TJYy$M{5^elee4(4-{?C@bEzqqPl*HOdn5zDPNcrKeX7uUth{;FJ3 zbichz~?)xXPWh0gw_Z4G(o02K!`PzGry7H;!2_HRiTIkPPaedE5 z;h2X=t?IhfZms&$4+Mm7Z77#69@Z!aetF~Yv(VaB61|wTk63Yl)Hm@^)>bc4pwTOg z^pPe!T-?mS3K}(dUM>Y`1-Z03xlAq0VVRyzpWm(~*r$(JuE)#oR(v~}&5v*7A+^6O-fi_JJ!OuO#4;MX>2v)Hr4V|w$#x_Cn7|)8HPI-;)EZOc_ z6x2VHx@+c!bjd{MmBO~0a47e@x-ik*C$(&tduk53!LXmso`qhOaY>Lzs(#vI2h`@{ zmT?8PEsO*HYvkO=M>VD1kMomt2N1nx zt@*{fuA8toEH_iEKui@?X&yb%-Q<0{UcDuTSVB6~+iK(>Mmkl^1ggxCyizMul3?7F zzy6ry-ONV1fxQ=Rf9!sVb2|JA+qc#;ZglW+89K4rXM`>63wt0^|N4D&IWVeUn7Sz+c;FI~6R zY2x>!6HPares8vK!5bXs?l~bBnQ=E1icgsE18txjfjXU8ea$5)!L#y<9;xz_8Ljae zK4dskZ1tGSnWVSZ6SLQ!6+(LFpT0~K*m3*a(2ww$OP)^BD^A*XdSepZ?0mrL=*ee; zzdbz4H_>tE>@i=PTWxi{g!$ooD-)!a5al`rQs|Q8EFZYRRgZC}O5`(r%@r!M_4TZ# zZe6}>N22g-BJMj8^j>Mj-jf?$X~PNbUDqzZpk{SW!82`TTN{7x$Vj}An5a8(<4fqD z)vp8thUn-%*}?04w9lQ*lvL<0vK+>xxHlA%g?-%PCnyQ{nemM(oL2UCc`*NbZQxwtF~D{NPOw`3SLy zL#!KnC3klI5-0j8cLPYx5S&l{tuqgngpHRYulpA+0s73eFQ%N0{ZQ$<5YwsWY4`Sx|g*HnXlu#(ycT*u{VnUXzWgGj%U~FT4=QWk6-rx6q-|zRY=ks|QGxvSn*L_~+ zd7Q^_oKvkeYi)I|v+}fC6^wTdWeA~BBC0XE%_zgK7+ z62L7u{Cdw!q=ER)#H51x>%s8zALb+xg`>|YxJP0n>N3X-NVqcdw_Q0Muemd&4Kcr- zVq#=i??aytR*^(uc0~a7L+$@R8-(d24Dgj-$;$O=gV+4CN8sa3t9_nR`?q8yw&>MF z=q(*@_ktT`x(n@r3*ILdE@|E0y?)26U8aIM>oZF=4@K1PiO;Nmn7c}y4x(IA8D$}> zsFmwsmoe?=2DaK}u-O;ryj?yo+Hmckx57VQjIxJcpY(38c7FA1J#B#&z*G;L`2q}f zJw5A*o}&#I7xJc_>wmy2whVOzXBN(v^m}4*c#X&y2qa3T1eq?EsQkEHl+69y(YH3J zb0~Og7YyAmz8f+8#BBxBE0fKC?8v%Y(?@l=uF0d~?HVkU)AO0ZKfg#=HhCY6Xe7|* zGu?cEqNC7au0C-HjqqQsPgmM|H9`msEQEpCpUTq;7p zo>K{kc6Ec`wwd;+qYrV2Ts}1OHnCBg_iHC+JDZ-dlL}^EFuWUv6a)#N5wu7{21;}7%RiiWXSd7*HNta`5`U6D8qCGZ?h;v zIE9aHiMe-D=y@2~5&}wW#Owq0qSkUQUE9xc%T{evM<2rk!M^|P%&pt8Te}h47LanD z9|s%u$y$-I%1xdI4{hEo?zlF2g$?tRWL$6({`%9tqd%U>Xc?LOaL)TQbEHhy!I2%z zf}EoLQD!B>L(z`U>UjNNulYUnC5O*4-i58|>Nu9!E4g5mh%&H(GFsW`-`J(RyjsR? zwRA1!Y=^yl`9v<|ZH#%+eCAhaE9NZlRRc)U`-!Ri6Uf3oEjQUEJ$Rhw>C^J|%S z-qN#}6TLVrjK>X!;Z=LKE~j_!6+d&py~{o;sjJRthf1b znM_s3XI8!1Y(BG=0j)>dA3QQ1Z99#&^Lo}l-`+BF$5p*nk=xC!RvBH6H(J2_9t>gn zTUD)HG)(WI`$2)7bIeBFaGRGthM#EFLdpVhRlVajN%)lLrE4 z$ITr8mN8vkaOlt1&)mUa=VX_0@wFJEIYGpjuY0|XRmlO_HL*Za`6FJy*8Fz@314Gc zZe5;(_L*GL^`#5u{J`%~>Sp0YSa!MdyS~wJw;_4R!7m>{X9+rhCOdN{=L8+}MV7F* zzim{f;jiPy4Od(V4_Z>cpESSXk)e^1C+U9~7L9!gDDIk*BN%n!tShu7T(M`%!crpK zcBz1i+s`OHvfBW&Tf17EWI(6F%g!XcY? zs;f6;>Vuez$Ii~q`EGJ3{8pbGusaRn&5LH8pUZ9a4Nm?MblxG0oDchAgQ|0+BSsP8yi zv1SZBweR8Lt8+RZn3tBn?D~i#t*)_3G7-Fn)yG@L_Bx-v4(#^yv36m(GwY%1>`04~ z9eGv^4VZ8_cjH7Zk*5Vjh573$woswLl)FC02%6pF?P7z+x>r{i#RRk%jr1xeJ}8n` zNGt@hLS|pzbR$VNM2#=}BFs5RDee-ajdpX)3uaAG3m)2h zd^7^PD_$2gijS0B{N&}$s-{S4WRV+teXhlB*-nqrEphiKw=f(B6UA$9gsK=v8J<)< z79~I{^~gT=oKMYo&y|kR>R4aSHLbM6hEW5l>w5(Pv??~g(b@S}K||D0RQc;2g#+qv zIF!vzXGg_FBLbJ%32x;SIsG{eHjDBgI&TRMX2-oxELw6>*)Yhc9e}9SVFDQ!7jm@L zutZNE8oq?{1p)V$*iB%ccT1AnXZ_l1y4MsB-9}n$-R)cf0`{Zcek!a08r4v}e zxYcVqH;FqRi7SJ76E%C?A3V1gRW|ZR(<~zuVVXN5H$Q-3SwA|y!)hi61hDOt1f&_5 z{iuiywrs^a$C)nM#7`{^=(e?<7&~X?8&KJ`Fz`_lKWKYfp|m!ztuyku-_Hh|i6MZH zs$ppf%u5~%k%59PdR%7Y)1~Q(&6sMF&{6OY&pCbibk_rI`%j)YIjA??-58SC4B(=2|u7v_|vOF4%rLp>#iRq+#@kMVz%;+q#YnU&|H58??94;f$SWJAgH9epy0%0;bmx?>|~o2T7D zpb|2vWyVk5GMWosgfVdk_un`t2cx{DCeNQ`=O25;QtDZ2Ioa`qc+`TFot-`89*5;7 z%hV`H*H}BZ%CJwISzP^6z6oXFfa<`So;$c3$hMVwlJA`O>Fr z9$wzV&FqRVpIu}eOIlG(v2gg!_4);vHT+hZnzjD5`!Z53gUvSFQdiWbY`2vpZ1{ z7XF5U{--bepWe@~7IQykyry|D!0{f%uj54l zF^6bwzqX{{gkD@V@u)NjCUEvUvkyA^cXL+yN^t)3)WJSZXG4)&Tj&bQ$CO;N^ae@y zfX5mWGGu49&tluH&qkg|&KsBIGrC?kU5(YJH5TtW?6g7CdR1jop&Yg{j;QTh>-$CV z14Yu4A}KX5K7M#yHS!9pUPt8M=>Yrn$0rR(_N^)Tn8ttV%5s{O*PRS4?7HQ-pD9rIK*Y9zY%HqxT%-=N2&%tKQ2?AB^G3t8|HB8B@zV=g zTU#oO?$KAsGD8_(aZ!&}O-GW3^4`Ow^Cy>cX-aXo)e>Q9?Lk`@-))acuiSODYmX{{ zn^(J=r>5dFH~!tNfK;bum{zMT8+_e5kmLqB^ltmo;$0p+8j(FcU3{@^?obGw-m>p@ zky~qR5h34WMXy}5+RZNAAB21YSP2Y`X79L?i`%I?!)tDk(C}To$SXZLt0mMqh__y< zVex_Eiu*RjcHr3pM^@opCqLxTwNZ#G+~0gmn{*<8^AdMB^P=*>lNf@Cjt8kB=RqeB=PkT01Y@zp5@P^F+l|Y9IS?t2MHcb^5GanjZntL%x z35%9r)0Qfg~&T4OV%xWR<5G+$4@G{1yhI?dGt?54Ehs~^A--S@ryc?NWZW$ zQ$d;NZ-6f`NluDs5YnveMh|Y`5iJk=^%- zWYnCiv_ND4O)QQCN}!N5TimW>1v_KD$<#SnL{d{#rNXc%fHMJ}P25 ztGAmkIjpHvyZU^~bJ`R&YEF4? zJiO)43SYFi-T7n`+EOS(yR)A^M{XIV;0=87xLrti1jdv?RlkpENx)@X)TbRbR-UlD z`)T|k-Ap#*`t77ehL=*|@2DHy81k(XAerVXvu-8wU{P3 zDGY~+G8MB8d#^?{$-&zL#*c{5-9d)waGjPkxrz*?yv>*DqwY7Gjuebmc!3hhBh9qg z2(4y7d3;WJGp5?0rM661)3f7Yi-t^7q4b+YoS3I;JKe9{$8a9Rlf)!twyWW3o1Tyk zg>Le|>ANSkm~WzG99g)%m2U+4ZfPa5+?nr{Guc_IZ!cT)EY0eq@WdtDGi>A)g~T-W zYE`vfvusOkcm1BR0OHXpDdvThN#h!?1ejS*k{s6Vk6Jsl`uyZ*!}%jk!(0#EWgfxD zi>WQ?Y|m8pWgEG$F7uKy@6g~wd)=eGTbP|5FOc)*<`j6^>>^MmyqqrgZZLC#FM)UR zVv$czN^FN`g}=TgYNfbY)VXJ_l|4d;)agFWQSzA8qS#G)!Y$)xjm$OaUp^;zgr1tu zylvf+gWGthVV)3P&&mp8{D+LH?%u~7?TxL)dS72>mG!7k#J_}M)UTm*?&^Y8k2XRz zFyE?HUG_D~V2HtSKG z@1qvjtp$}sS990~bDXQsScNMJJJ~PdhiU{j;toa(j+nv(q6|zfa~Vy@GgkC13zw`N zXv>Dq(3y+;@!_)Xa^hvhpU3UFBtOD4(5+1#Oc?)kBEn-;q(_r}|4qL0lVX`=2bzY{ zJl~q5u9r;1<|I_t;;5RmYn~4b)(#5rR}0=+ug>ef0hZRi@vMM1XSI%!;x~a#+~Gs3 z+fy~&1FNw-g!S`$oTQsF1aD>Bp2o>}?wuSEAV?^Or!|E%kN}E)V6@R|{spF=wI*XJ zbu6QzFrOSW@sp2yW|pw0_pSIP)AQ#sRVRI_O|q37mznToYAC<4g2&k=*{*M|oqgRlOL6 zyQ|+wT^|a#h~$f=TwZ$;-I~8WeYq(MnB+}`}!#`)}=Zoai>G#-KIG?KCG{fm@O!=U__@L9&onvC}BU83Mv&*Sh2*w=lZC0}1fsB>K}<9Z}Jx$2B9Hn%;N^Laf0t*wOT(dTK_Z{3D;up1#zZalCjxd{)0;;4;h|A`?U zZ5sYG50_N9aT2 z(O>gVDL7jsG}KmY=Raw<;n^alp>K+!))S(!75tT!ODC|SN+KI#NkZ)HRnf+@w=U(& zQ^}_ak0N(zg1d0$19^poA6uoaxG=!@zcyH3x0!qd-01wf>Fcu6FI1tPCmmR6V|y5>PwQ0EXZ%#`D^E$s*I!WO_mB zhrx&Jo@0d_ZV}L}456@9muDqGj*TlXbZSO2SspM5vKfD9=Hrm&3_jp`vV6RE0Qu<3 zb9l*HwUI4MFvLujzo!IzDBJ)f|$J}4t!AK?joX^hrBMgQ9wsN3fw)P|>4M=nIz6Bw$)%e5HMDP&v{5-PehCyKo zX-h0A@@`K?;H!5bFl4Vh?PaBDOv~_|Qf18#yYqdAcl*)6)8%!N8Uisc>w@FWIHCr&0UD846_+Pm<1yqI0jKmKf~=#1&uRn%6on433hr-ggZ>cECgPuPk+ah|nw zMR*InyhX|W>fteg*ci6#3;aYWUWiFZ2P-0~(x z)q^~~XOF8&!eqL$78Vy{^u@>BKoApNl@pKwv%BoaTUOV|CVqO~V(qeUn?5zCwpvVM zN~-ywUYu!D-X$!KSY6&S>{9K%ncrC`ILXET#&ENcTTqRXMO@D`A8*B$)f}r}gDMkm zlutNG(;sRUvYv2`Lhm8IyW;lx=uPbnNjY@Sb|L=m>=@+&H^Ey@>eOD!r?B;uV?rwu z9VTlmQ{y{gOH8G&EvYo`AXCr?+giIjJ<4n+2G=CUJKU>%KDkSlC-i27}+4cPDD9+uc)K{ zav(2!?_^G2qv8G_nj!29kc(#Px>2ruzQ<$jBS&&x$!j$Yd*Gt91}84=n`UKhv?&B4 z5uTb)zK7w@W6)d*FyWiDOuYvn;^$LjxRg zN5eK^+VO+8tnIfOBxasYLR70317D>ep~H6oNQX)&Fy@tV6KP`vPqchHVg0FzL{UkZ z41tE4L57htrusdN%9i6vQcy+J3e>V~KA^iArw1oV$!Q?{Yc$VpsNx zjHdTon2$9cZyt`7yf3s|)HKvRb0F(MMy(vJN^ZL=;mV$zLms^>EH`$U$QpD6mg(CzB?Kbwoa@@0Ek559WabgsWirtt=lKU8m9 z1xA^?&}-!(F^WsVi2c&}Y zZ68bQXZo`o?7p zw$<^@a-WyLBV<<8zoBxw&1q1>1%X5)nkz)AY8UCy|JCNOs_N+|~!L~Ccb zbvc8N^jq?u;z^%QxsLcy>y<(4(Q{AZ_?8zrJ@I*;Q+~Es;r>f5@v*ke@Ol{cxi4r) z{xw)1>P}N(kjlkD+Y@Q{@~A6pTj`Ss1s?+wBfY-H z?A@MbK4|05XMQF2hA9g zT?*YrP9QngN#gNyc{Fd0XdiS*(*HP2y2&~t$>l4rdn_!Ao`DBv?$|UH-x9|7)#xQ$ znxuKZ=r?bTpl=nD-`4@C;4}T9J0b05{()}oLVA{uGpt*ht2^TpUi4gC8K_lkHzeUX zB7SR|ZPm+UoN#`bfqS%{+P`@wF>D zaKMa`Q=2bleG>IF`^+f!;-oiOpPXuHq3IEOwWQSEKp|9B)rn4R?Qk0q<~XG92fT1- zbFmJHm0w68Mr`wwtg%*qSA8-JsqZnf1IJBj+BhSlmH7JcAbYZ3~kVYh|8tbY%(QG8OaKyVzD0}nffLb`5!R~sNZx~gmgt$wEKl~ml>qb8G zLip=3gKKq*iz~aYt^c|Dyn{nVTp1wIwbh%8+}|cx9^d!%D*ONbJxX{ zgfpwiLe`YzK=;H1)iJoirWX=uK5_FCC!%X})$XK5gn&j!AkZSi^+Vp2GD(@x(0U;OW0&mI!gD68N(P_ScOteCWplB)!DRgl z2}CxhZ0;D`>6yPT;8d}#gtcAqDsB7p (rYT@kQ#{`Q*FleUnVjFEsU}Zr^j5pOE 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 |I%r_4O!bA%bkgvIv?6;de_}8%3hYAE}SoRlsV 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 X7P4<{s(AY9)AJDr0{zN-f64eiTuPVb literal 0 HcmV?d00001 diff --git a/static/img/standalone_Tokenized_Refund_and_reversals.png b/static/img/standalone_Tokenized_Refund_and_reversals.png new file mode 100644 index 0000000000000000000000000000000000000000..4da9dc426170672ad9a8d8fd2c7ab98eb665b629 GIT binary patch literal 108857 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 + +

    + +:::tip +If you are currently using 3.x of the iOS SDK, take a look at the [migration guide](iosmigration.md) to 4.x +::: + + +The Handpoint iOS SDK provides a simple application programming interface for the Handpoint payment terminals. + +:::info +Please note that before submitting an app to the Apple App store a MFi hardware request has to be submitted to Apple, +to be able to use an external accessory. Please fill our [this form](http://hndpt.co/hp-mfi) before submitting your app to the App store and we will get back to you. +If you have any questions, contact us for more details. +::: diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosmigration.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosmigration.md new file mode 100644 index 0000000..d99260b --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosmigration.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 3 +id: iosmigration +--- + + + + +# Migration from 3.X + + +:::tip +Version 4.0.0 introduces a well defined, typed, way of passing extra values, options, parameters or flags to the financial transactions. +::: + + +We have unified all the extra and optional parameters in an Options object. Different operations have different options. + +**1. For a [Sale](iostransactions.md#2) or [Sale and Tokenize](iostransactions.md#4) operation**
    If you use a customer reference: + +``` + SaleOptions *options = [SaleOptions new]; + options.customerReference = @"Your customer reference"; +``` + + +If you need Multi MID / Custom merchant Authentication: + + +````objectivec + MerchantAuth *auth = [MerchantAuth new]; + Credential *cred = [Credential new]; + //Optionally + cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; + //Optionally + cred.mid = @"mid"; + //Optionally + cred.tid = @"tid"; + //Add as many credentials as Acquirers your merchant have agreements with + [auth add:cred]; + options.merchantAuth = auth; +```` + +If you want to specify the budget period Only available for `SureSwipe/Altech` (South Africa): + +````objectivec +options.divideByMonths = @"YOUR_BUDGET_NUMBER"; + ```` + +Finally: + +````objectivec +[self.api saleWithAmount:amount currency:currency options:options]; +```` + + +**2. for a [Refund](iostransactions.md#5) operation (less optional parameters)**
    If you use a customer reference: + +````objectivec + SaleOptions *options = [SaleOptions new]; + options.customerReference = @"Your customer reference"; +```` + +If you need Multi MID / Custom merchant Authentication: + +````objectivec +MerchantAuth *auth = [MerchantAuth new]; + Credential *cred = [Credential new]; + //Optionally + cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; + //Optionally + cred.mid = @"mid"; + //Optionally + cred.tid = @"tid"; + //Add as many credentials as Acquirers your merchant have agreements with + [auth add:cred]; + options.merchantAuth = auth; +```` +Finally: + +```objectivec +[self.api refundWithAmount:amount currency:currency transaction:originalTransactionID options:options]; +``` + +**3. For the rest of operations**
    If you use a customer reference: + +```objectivec +options.customerReference = @"Your customer reference"; +``` \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md new file mode 100644 index 0000000..ce8d0a0 --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md @@ -0,0 +1,762 @@ +--- +sidebar_position: 11 +id: iosobjects +--- + + +# Objects + +## HeftManager{#19} + +`HeftManager` Object + +The HeftManager is used for discovering and connecting to devices as well as creating a HeftClient object for the appropriate payment terminal. The manager reports messages to the HeftDiscoveryDelegate protocol during the discovery process. Starting the manager is the first thing to be done after loading up an UIView which enables the user to search for and connect to bluetooth terminals. When starting the manager an object (usually the UIViewController itself) is passed as the HeftDiscoveryDelegate delegate to report to. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `devicesCopy`
    *NSArray* | **DEPRECATED_ATTRIBUTE**: Array which contains the discovered payment terminals.| +| `connectedCardReaders`
    *NSArray* | Array which contains the discovered payment terminals.| +| `delegate`
    *NSObject*| Key for value in mpedInfo.| +| `version`
    *NSString* | Current HeftManager version.| + +**Code example** + +````objectivec +// Create a manager on view load +- (void)viewDidLoad{ + [super viewDidLoad]; + HeftManager* manager = [HeftManager sharedManager]; + manager.delegate = self; + [manager resetDevices]; // Clean out the payment terminal list +} +```` + +**Methods** + +[**Start Discovery**](iosdevicemanagement.md#32) + +- (void)startDiscovery; +*** + +[**Shared Manager**](iosdevicemanagement.md#11) + ++ (HeftManager `*`)sharedManager; +*** + +[**Client for device (NSString)**](iosdevicemanagement.md#12) + +- (void)clientForDevice:(HeftRemoteDevice `*`)device sharedSecret:(NSString `*`)sharedSecret delegate:(NSObject HeftStatusReportDelegate `*`)delegate; + +## HeftClient{#22} + +`HeftClient` Object + +High level interface for the API. HeftClient handles the communication between your application and the payment terminal. The HeftClient object also stores information about the payment terminal in the mpedInfo dictionary. Device Log operations are also implemented in HeftClient. To create a new HeftClient object the clientForDevice method is called from an instance of the HeftManager. Transaction and log requests (and the acceptSignature response) are done by calling HeftClient methods with the relevant input. The library reports the status of the requests by calling delegates of the HeftStatusReportDelegate protocol. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `sharedSecret`
    *NSString* | The shared secret is a unique authentication key provided by Handpoint for each merchant.| +| `mpedInfo`
    *NSDictionary* | Dictionary with payment terminal details, obtained from the device on interface creation.| +| `isTransactionResultPending`
    *BOOL* | Indicates whether a transaction result is pending on the payment terminal.

    **Note: A pending transaction result is retained by the payment terminal if a disconnect occurs between the terminal and your application before the transaction result can be delivered during a SALE, REFUND or VOID operation.**| +| `kSerialNumberInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kPublicKeyVersionInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kEMVParamVersionInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kGeneralParamInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kManufacturerCodeInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kModelCodeInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kAppNameInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kAppVersionInfoKey`
    *NSString Constant* | Key for value in mpedInfo| +| `kXMLDetailsInfoKey`
    *NSString Constant* | Key for value in mpedInfo| + + +**Code example** + +````objectivec +//clientForDevice:sharedSecret:delegate: +//Creates a HeftClient object(connection to device) +-(void)connectToFirstCardReaderWith:(NSData*)sharedSecret; +{ + //Try to connect to the first device in the devices array + [heftManager clientForDevice:[[heftManager devicesCopy] objectAtIndex:0] sharedSecret:sharedSecret delegate:self]; + //Client calls the didConnect delegate function if successful +} + +//.... + +//didConnect: +//Called when a connection to a specified device was created. +-(void)didConnect:(id)client +{ + // connected successfully to a device + // assigned the client to the heftClient property + heftClient = client; +} + +// ..... + +// Do one sale later in code +[heftClient saleWithAmount:1000 currency:@"GBP" cardholder:YES]; +```` + +**Methods** + +[**cancel**] + +- (void)cancel; +*** + +[**saleWithAmount**](iostransactions.md#2) + +- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present; +*** + +[**saleWithAmount**](iostransactions.md#2) + +- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference; +*** + +[**saleWithAmount**](iostransactions.md#2) + +- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference divideBy:(NSString*)months; +*** + +[**refundWithAmount**](iostransactions.md#5) + +- (BOOL)refundWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present; +*** + +[**refundWithAmount**](iostransactions.md#5) + +- (BOOL)refundWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference; +*** + +[**saleVoidWithAmount**](iostransactions.md#3) + +- (BOOL)saleVoidWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present transaction:(NSString*)transaction; +*** + +[**refundVoidWithAmount**](iostransactions.md#6) + +- (BOOL)refundVoidWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present transaction:(NSString*)transaction; +*** + +[**retrievePendingTransaction**](iostransactions.md#8) + +- (BOOL)retrievePendingTransaction; +*** + +[**enableScanner**](iosdevicemanagement.md#36) + +- (BOOL)enableScanner; +*** + +**enableScannerWithMultiScan** + +- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan; +*** + +**enableScannerWithMultiScan** + +- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan buttonMode:(BOOL)buttonMode; +*** + +**enableScannerWithMultiScan** + +- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan buttonMode:(BOOL)buttonMode timeoutSeconds:(NSInteger)timeoutSeconds; +*** + +[**Disable scanner**](iosdevicemanagement.md#disable-scanner) + +- (BOOL)disableScanner; +*** + +**financeStartOfDay** + +- (BOOL)financeStartOfDay; +*** + +**financeEndOfDay** + +- (BOOL)financeEndOfDay; +*** + +[**financeInit**](iosdevicemanagement.md#47) + +- (BOOL)financeInit; +*** + +[**logSetLevel**](iosdevicemanagement.md#33) + +- (BOOL)logSetLevel:(eLogLevel)level; +*** + +[**logReset**](iosdevicemanagement.md#35) + +- (BOOL)logReset; +*** + +[**logGetInfo**](iosdevicemanagement.md#34) + +- (BOOL)logGetInfo; +*** + +[**acceptSignature**](iostransactions.md#7) + +- (void)acceptSignature:(BOOL)flag; +*** + +**getEMVConfiguration** + +- (BOOL)getEMVConfiguration; +*** + +## HeftRemoteDevice{#23} + +`HeftRemoteDevice` Object + +An object containing a reference to the accessory device which is passed to the HeftClient on creation. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `name`
    *NSString* | Name of device| +| `accessory`
    *EAAccessory* | The EAAccessory object| +| `address`
    *NSString* | Address of device| + + +## HeftDiscoveryDelegate + +`HeftDiscoveryDelegate` + +Notifications sent by the SDK on various events - new available device found, connection lost, connection found, etc + +**Methods** + +[**didDiscoverFinished**](iosevents.md#37) + +- (void)didDiscoverFinished; +*** + +[**didFindAccessoryDevice**](iosevents.md#38) + +- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice; +*** + +[**didLostAccessoryDevice**](iosevents.md#39) + +- (void)didLostAccessoryDevice:(HeftRemoteDevice*)oldDevice; +*** + +## HeftStatusReportDelegate + +`HeftStatusReportDelegate` Object + +Notifications sent by the SDK on various events - connected to device, request signature, response on error etc. + +**Methods** + +[**didConnect**](iosevents.md#20) + +- (void)didConnect:(id-HeftClient)client; +*** + +[**responseStatus**](iosevents.md#14) + +- (void)responseStatus:(id-ResponseInfo)info; +*** + +[**responseError**](iosevents.md#15) + +- (void)responseError:(id-ResponseInfo)info; +*** + +[**responseFinanceStatus**](iosevents.md#16) + +- (void)responseFinanceStatus:(id-FinanceResponseInfo)info; +*** + +[**responseLogInfo**](iosevents.md#43) + +- (void)responseLogInfo:(id-LogInfo)info; +*** + +[**requestSignature**](iosevents.md#17) + +- (void)requestSignature:(NSString*)receipt; +*** + +[**cancelSignature**](iosevents.md#40) + +- (void)cancelSignature; +*** + +[**responseRecoveredTransactionStatus**](iosevents.md#44) + +- (void)responseRecoveredTransactionStatus:(id-FinanceResponseInfo)info; +*** + +[**responseScannerEvent**](iosevents.md#41) + +- (void)responseScannerEvent:(id-ScannerEventResponseInfo)info; +*** + +[**responseScannerDisabled **](iosevents.md#42) + +- (void)responseScannerDisabled:(id-ScannerDisabledResponseInfo)info; +*** + +**responseEMVReport** + +- (void)responseEMVReport:(NSString *)report; +*** + + +## ResponseInfo{#24} + +`ResponseInfo` Object + +A ResponseInfo object is passed to the ResponseStatus delegate. It contains information from the payment terminal about the status of the current transaction. There are two properties: status and xml. status is a string and xml is a dictionary. Usually status contains a descriptive enough message to know what is going, this messsage should be displayed to the yser. The xml dictionary has detailed information on the current state of the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `statusCode`
    *int* | A numerical representation of the status.| +| `status`
    [*Status as NSString*](#45) | Status message of the financial operation.| +| `xml`
    [*XML as NSDictionary*](#46) | Details of the transaction.| + + +## FinanceResponseInfo{#25} + +`FinanceResponseInfo` Object + +A FinanceResponseInfo is passed to the responseFinanceStatus delegate at the end of a transaction. It contains all necessary information about the outcome of the transaction. FinanceResponseInfo inherits from ResponseInfo so it includes the status string and xml dictionary in addition to the authorisedAmount, transactionId and the html formatted receipts. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `financialResult`
    *NSInteger* | A numerical representation of a financial status result.
    EFT_FINANC_STATUS_UNDEFINED 0x00
    EFT_FINANC_STATUS_TRANS_APPROVED 0x01
    EFT_FINANC_STATUS_TRANS_DECLINED 0x02
    EFT_FINANC_STATUS_TRANS_PROCESSED 0x03
    EFT_FINANC_STATUS_TRANS_NOT_PROCESSED 0x04
    EFT_FINANC_STATUS_TRANS_CANCELLED 0x05| +| `isRestarting`
    *BOOL* | Indicates whether the card reader is about to restart or not (usually triggered after a software update is received).If a restart is imminent then you have 2 seconds to start fetching the logs (before the card reader restarts). After fetching the logs you should disconnect from the card reader and wait for it to be visible again.| +| `authorisedAmount`
    *NSInteger* | Amount in the smallest unit of the currency - For example 1000 in case the CurrencyCode is "0826" (GBP) corresponds to 10.00 pounds.| +| `transactionId`
    *NSString* | The id of the current transaction.| +| `customerReceipt`
    *NSString* | Customer receipt in html format.| +| `merchantReceipt`
    *NSString* | Merchant receipt in html format.| +| `statusMessage`
    *NSString* | A human readable message describing the result of the transaction.| +| `type`
    *NSString* | Type of financial operation ("SALE" is an example).| +| `finStatus`
    *NSString* | The financial status describes the outcome of the transaction("AUTHORISED" is an example).| +| `requestedAmount`
    *NSString* | Amount sent in the original request to the payment terminal.| +| `gratuityAmount`
    *NSString* | The gratuity amount is an additional amount (for example a tip) added to the requested amount. This field is returned when the tipping functionality is activated on the payment terminal.

    Example: a sale is started for 10.00 and the payment terminal is set to support tipping. The terminal asks the cardholder if a tip should be added for the transaction. The cardholder inputs an additional amount as a tip, lets say 1.00. The card is then charged for the requested amount, 10.00, as well as the additional gratuity amount, 1.00. The resulting charge will be for a total of 11.00.| +| `gratuityPercentage`
    *NSString* | The gratuity percentage is used to calculate an additional amount (for example a tip) added to the requested amount. The terminal calculates the gratuity amount based on the percentage chosen by the cardholder on the payment terminal, the amount is rounded up to the closest whole number.

    Example: a sale is started for 10.00 and the payment terminal is set to support tipping. The terminal asks the cardholder if a tip should be added for the transaction. The cardholder chooses a % as a tip, lets say 10%. The card is then charged for the requested amount, 10.00, as well as the additional gratuity amount, 1.00 (10%). The resulting charge will be for a total of 11.00.| +| `totalAmount`
    *NSString* | The total amount is the amount for which the card was charged in the minor unit of the currency. It is possible for the total amount to be different from the requested amount if a tip is added or the transaction is partially approved (US acquirers only).| +| `currency`
    *NSString* | The currency used for the transaction.| +| `eFTTransactionID`
    *NSString* | The EFT (electronic funds transfer) transaction id is a unique GUID assigned to the transaction. This id is used as a parameter for the sale or refund reversal function in case the transaction needs to be reversed.| +| `originalEFTTransactionID`
    *NSString* | This field is only returned in a reversal or refund transaction and references the GUID of the original transaction being refunded or reversed.| +| `eFTTimestamp`
    *NSString* | The eFTTimestamp is the time at which the transaction was processed.| +| `authorisationCode`
    *NSString* | This is the approval code returned by the payment processor when a transaction is approved.| +| `verificationMethod`
    *NSString* | Cardholder verification method, for example "PIN".| +| `cardEntryType`
    *NSString* | Method used by the terminal to read the card.| +| `cardSchemeName`
    *NSString* | A string representing different card brands (VISA, Mastercard, etc...)| +| `errorMessage`
    *NSString* | Detailed reason for the transaction error.| +| `customerReference`
    *NSString* | If a customer reference was added, as an optional parameter, when the transaction was started. It is received here, unaltered. The customer reference can be used at your will for tracking of transactions.| +| `budgetNumber`
    *NSString* | If a budget number was added, as an optional parameter, when the transaction was started. It is received here, unaltered. The budget number can be used to split payments over a period of months.| +| `recoveredTransaction`
    *BOOL* | This flag is true if the transaction result retrieved is from a previous transaction which failed to get sent from the payment terminal to your application, false otherwise. In case the communication between your application and the terminal breaks down, the terminal will attempt to send the result of the previous transaction as an immediate reply when the next transaction is started. If this happens, the transaction is flagged as a "RecoveredTransaction".| +| `cardTypeId`
    *NSString* | DEPRECATED - The card type id is an identifier inside the Handpoint gateway which represents what kind of card was used. "U015" for an example represents SAS Airline-Systems in our systems.| +| `chipTransactionReport`
    *NSString* | If present, a full report of the card EMV parameters.| +| `deviceStatus`
    *NSString* | Gets the device status.| +| `dueAmount`
    *NSString* | If there's still a part of the amount to be paid, in case of a partial approval (US acquirers only).| +| `balance`
    *NSString* | The balance of the cardholder's card, if the bank/acquirer supports it.| +| `CardToken`
    *NSString* | Token representing the PAN of the card.| + + +## ScannerEventResponseInfo{#26} + +`ScannerEventResponseInfo` Object + +A ScannerEventResponseInfo is passed to the responseScannerEvent delegate when a scan is detected. ScannerEventResponseInfo inherits from ResponseInfo so it includes the status string and xml dictionary in addition to the scanCode string. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `statusCode`
    *int* | A numerical representation of the status.| +| `status`
    [*Status as NSString*](#45) | Financial transaction status message.| +| `xml`
    [*XML as NSDictionary*](#46) | Feedback with xml details about transaction from the card reader.| +| `scanCode`
    *NSString* | The code that was scanned.| + +## ScannerDisabledResponseInfo{#27} + +`ScannerDisabledResponseInfo` Object + +This object contains information about the scanner operation. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `statusCode`
    *int* | A numerical representation of the status.| +| `status`
    [*Status as NSString*](#45) | Financial transaction status.| +| `xml`
    [*XML as NSDictionary*](#46) | XML details from the payment terminal.| + +## LogInfo{#28} + +`LogInfo` Object + +A LogInfo object is passed to the ResponseLogInfo delegate when logs have been downloaded from the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `statusCode`
    *int* | A numerical representation of the status.| +| `status`
    [*Status as NSString*](#45) | Financial transaction status.| +| `xml`
    [*XML as NSDictionary*](#46) | XML details from the payment terminal.| +| `log`
    *NSString* | String containing the logging information.| + +## eLogLevel{#13} + +`eLogLevel` Enum + +An enum describing the different levels of logging used in the SDK and in the payment terminal. + +**Possible values** + +`eLogNone` `eLogError` `eLogInfo` `eLogFull` `eLogDebug` + +## Transaction Details{#46} + +`XML as NSDictionary` Object + +The contents of the xml property depend on which type of operation the payment terminal is responding to. Listed below are all possible keys in the dictionary. Note that not all fields are included all the time. + +**StatusMessage** + +The status of the transaction, for example "Waiting for pin". +*** + +**TransactionType** + +The type of transaction performed: UNDEFINED SALE VOID_SALE REFUND VOID_REFUND REVERSAL, TOKENIZE_CARD SALE_AND_TOKENIZE_CARD +*** + +**FinancialStatus** + +The result of the transaction: UNDEFINED AUTHORISED DECLINED PROCESSED FAILED CANCELLED PARTIAL_APPROVA +*** + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED`
    | Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | +| `AUTHORISED`
    | The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | +| `DECLINED`
    | The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
    | The `update` operation was successful.| +| `FAILED`
    | Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | +| `CANCELLED`
    | The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
    | A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | + + +**RequestedAmount** + +The requested amount is the transaction amount sent to the terminal. +*** + +**GratuityAmount** + +The gratuity amount entered by the cardholder, if any. +*** + +**GratuityPercentage** + +The gratuity amount, as a percentage of the requested amount. +*** + +**TotalAmount** + +The total of the gratuity and requested amount. +*** + +**TransactionID** + +The transaction number used for this transaction, as maintained by the Eft Client. +*** + +**EFTTransactionID** + +The EFT reference, given by the system, to make the transaction unique. +*** + +**OriginalEFTTransactionID** + +The original EFT reference, given by the POS, as part of a VOID_SALE or a VOID_REFUND transaction. +*** + +**EFTTimestamp** + +The date and time of the transaction, in ISO format (YYYYMMDDHHmmSS). +*** + +**AuthorisationCode** + +The transaction authorization code, as given by the system. +*** + +**CVM** + +The Cardholder Verfication Method: UNDEFINED, SIGNATURE, PIN, PIN_SIGNATURE, FAILED, NOT_REQUIRED +*** + +**CardEntryType** + +The card data acquisition type: UNDEFINED, MSR, ICC, CNP +*** + +**CardSchemeName** + +The card brand : MasterCard, Visa, Maestro, American Express, Discover, JCB, Diners, UnionPay +*** + +**CardTypeId** + +DEPRECATED - The ID of the Card Type. +*** + +**SerialNumber** + +The serial number of the payment terminal. +*** + +**BatteryStatus** + +A number, followed by the % sign, which indicates the current charge level of the battery. +*** + +**BatterymV** + +An integer, which represent the battery charge, in mV. +*** + +**BatteryCharging** + +Indicates whether the battery is charging, or not. Values are true or false. +*** + +**ExternalPower** + +Indicates whether the PED is connected to an external power source (e.g. a AC adapter). Values are true or false. +*** + +**ApplicationName** + +The name of the application running on the payment terminal. +*** + +**ApplicationVersion** + +A version string of the form major.minor.build”(e.g. 1.2.118). +*** + +**ErrorMessage** + +Description of the error, if any. +*** + +**RecoveredTransaction** + +Indicates that the transaction result is a recovered transaction. The key is only included if value is true. +*** + +## CmdIds + +`card reader Status messages` Value List + +Status messages received from the payment terminal: + +**Possible values** + +`EFT_PP_STATUS_SUCCESS`
    +`EFT_PP_STATUS_INVALID_DATA`
    +`EFT_PP_STATUS_PROCESSING_ERROR`
    +`EFT_PP_STATUS_COMMAND_NOT_ALLOWED`
    +`EFT_PP_STATUS_NOT_INITIALISED`
    +`EFT_PP_STATUS_CONNECT_TIMEOUT`
    +`EFT_PP_STATUS_CONNECT_ERROR`
    +`EFT_PP_STATUS_SENDING_ERROR`
    +`EFT_PP_STATUS_RECEIVING_ERROR`
    +`EFT_PP_STATUS_NO_DATA_AVAILABLE`
    +`EFT_PP_STATUS_TRANS_NOT_ALLOWED`
    +`EFT_PP_STATUS_UNSUPPORTED_CURRENCY`
    +`EFT_PP_STATUS_NO_HOST_AVAILABLE`
    +`EFT_PP_STATUS_CARD_READER_ERROR`
    +`EFT_PP_STATUS_CARD_READING_FAILED`
    +`EFT_PP_STATUS_INVALID_CARD`
    +`EFT_PP_STATUS_INPUT_TIMEOUT`
    +`EFT_PP_STATUS_USER_CANCELLED`
    +`EFT_PP_STATUS_INVALID_SIGNATURE`
    +`EFT_PP_STATUS_WAITING_CARD`
    +`EFT_PP_STATUS_CARD_INSERTED`
    +`EFT_PP_STATUS_APPLICATION_SELECTION`
    +`EFT_PP_STATUS_APPLICATION_CONFIRMATION`
    +`EFT_PP_STATUS_AMOUNT_VALIDATION`
    +`EFT_PP_STATUS_PIN_INPUT`
    +`EFT_PP_STATUS_MANUAL_CARD_INPUT`
    +`EFT_PP_STATUS_WAITING_CARD_REMOVAL`
    +`EFT_PP_STATUS_TIP_INPUT`
    +`EFT_PP_STATUS_SHARED_SECRET_INVALID`
    +`EFT_PP_STATUS_SHARED_SECRET_AUTH`
    +`EFT_PP_STATUS_WAITING_SIGNATURE`
    +`EFT_PP_STATUS_CONNECTING`
    +`EFT_PP_STATUS_SENDING`
    +`EFT_PP_STATUS_RECEIVEING`
    +`EFT_PP_STATUS_DISCONNECTING`
    +`EFT_PP_STATUS_PIN_INPUT_COMPLETED`
    +`EFT_PP_STATUS_POS_CANCELLED`
    +`EFT_PP_STATUS_REQUEST_INVALID`
    +`EFT_PP_STATUS_CARD_CANCELLED`
    +`EFT_PP_STATUS_CARD_BLOCKED`
    +`EFT_PP_STATUS_REQUEST_AUTH_TIMEOUT`
    +`EFT_PP_STATUS_REQUEST_PAYMENT_TIMEOUT`
    +`EFT_PP_STATUS_RESPONSE_AUTH_TIMEOUT`
    +`EFT_PP_STATUS_RESPONSE_PAYMENT_TIMEOUT`
    +`EFT_PP_STATUS_ICC_CARD_SWIPED`
    +`EFT_PP_STATUS_REMOVE_CARD`
    +`EFT_PP_STATUS_SCANNER_IS_NOT_SUPPORTED`
    +`EFT_PP_STATUS_SCANNER_EVENT`
    +`EFT_PP_STATUS_BATTERY_TOO_LOW`
    +`EFT_PP_STATUS_ACCOUNT_TYPE_SELECTION`
    +`EFT_PP_STATUS_BT_IS_NOT_SUPPORTED`
    +`EFT_PP_STATUS_PAYMENT_CODE_SELECTION`
    +`EFT_PP_STATUS_PARTIAL_APPROVAL`
    +`EFT_PP_STATUS_AMOUNT_DUE_VALIDATION`
    +`EFT_PP_STATUS_INVALID_URL`
    +`EFT_PP_STATUS_WAITING_CUSTOMER_RECEIPT`
    +`EFT_PP_STATUS_PRINTING_MERCHANT_RECEIPT`
    +`EFT_PP_STATUS_PRINTING_CUSTOMER_RECEIPT`
    +`EFT_PP_STATUS_WAITING_HOST_MSG_TO_HOST`
    +`EFT_PP_STATUS_WAITING_HOST_MSG_RESP`
    +`EFT_PP_STATUS_INITIALISATION_COMPLETE`
    + + +## Status strings{#45} + +`Status as NSString` Value List + +An NSString containing the status message - can be one of the following: + +**Possible values** + +`Success`
    +`Invalid data`
    +`Processing error`
    +`Not allowed`
    +`Not initialized`
    +`Connect timeout`
    +`Connect error`
    +`Sending error`
    +`Receiveing error`
    +`No data available`
    +`Transaction not allowed`
    +`Unsupported currency`
    +`No host available`
    +`Card reader error`
    +`Card reading failed`
    +`Invalid card`
    +`Input timeout`
    +`User cancelled`
    +`Invalid signature`
    +`Waiting card`
    +`Card inserted`
    +`Application selection`
    +`Application confirmation`
    +`Amount validation`
    +`PIN input`
    +`Manual card input`
    +`Waiting card removal`
    +`Tip input`
    +`Shared secret invalid`
    +`Connecting`
    +`Sending`
    +`Receiving`
    +`Disconnecting`
    +`PIN entry completed`
    +`Merchant cancelled the transaction`
    +`Request invalid`
    +`Card cancelled the transaction`
    +`Blocked card`
    +`Request for authorisation timed out`
    +`Request for payment timed out`
    +`Response to authorisation request timed out`
    +`Response to payment request timed out`
    +`Please insert card in chip reader`
    +`Remove the card from the reader`
    +`This device does not have a scanner`
    +`Scanner is not supported`
    +`Scanner event`
    + +## Process details + +The following table contains result codes that can occur in the COMMAND response STATUS field (see section 1.3 above). + +In addition the following table contains the text information presented in the StatusMessage field that is part of the FinancialTransactionResponse Xml response object. + +All values are in hex in the following table. + +| Status ID | Value | StatusMessage| Details | +| ----------- | ----------- |----------- | ----------- | +| EFT_SUCCESS | 0001| One of the following: "" (an empty string) "AUTH CODE #" "REFUND ACCEPTED" "REVERSAL ACCEPTED"|Operation completed successfully. No further actions required.| +| EFT_INVALID_DATA | 0002|"Invalid data"|Invalid COMMAND request object, from the POS App, at the start of an operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| +|EFT_PROCESSING_ERROR |0003| "Processing error"| An unexpected error occurred during processing. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| +|EFT_COMMAND_NOT_ALLOWED| 0004| "Command not allowed"| The card reader is currently busy processing another command. Please retry the operation once the current operation has completed.|| +|EFT_NOT_INITIALISED |0005 |"Device is not initialized"| The current operation can’t be completed because there is a pending software update that must be applied before processing can continue. Please retry the operation after the card reader has restarted itself.| +|EFT_CONNECT_TIMEOUT |0006 |"Connection time out detected"| The back end connection timed out during an update. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| +|EFT_CONNECT_ERROR |0007 |"Connection error" |It was not possible to establish a connection to the back end system during an update operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| +|EFT_SENDING_ERROR |0008 |"Send error" |A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| +|EFT_RECEIVING_ERROR |0009| "Receiving error"| A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| +|EFT_NO_DATA_AVAILABLE |000A| "No data available"| The POS App is trying to fetch the card reader log file but there is no data stored in the log file. If logs are required then please set the log level to an appropriate value and retry the operation.| +|EFT_TRANS_NOT_ALLOWED |000B| "Transaction not allowed"| `Currently not used`| +|EFT_UNSUPPORTED_CURRENCY| 000C| "Currency not supported"| A currency has been selected that the card reader has not been configured for. Please select the correct currency and retry the operation. Alternatively, please contact technical support and ask for the specific currency to be supported.| +|EFT_NO_HOST_AVAILABLE| 000D |"No host configuration found"| An update was initiated but the card reader could not find any host information for the back end system, even though it otherwise contains valid configuration. This is indicative of an invalid `hostBlock` block with in the `HostList` block in this device configuration, which was placed on the card reader during a previous update. Please contact technical support and provide card reader logs and ask for a replacement device. The card reader will be unable to update itself and must be replaced.| +|EFT_CARD_READER_ERROR |000E |"Card reader error"| Error detected in the chip reader or the magnetic stripe reader. Please retry the operation. If the issue persists please contact technical support and provide them with the card reader logs as well as asking for a replacement reader.| +|EFT_CARD_READING_FAILED| 000F| "Failed to read card data"| The card reader could not read any data from the card. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| +|EFT_INVALID_CARD |0010 |"INVALID CARD" |The card reader detected invalid card data. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| +|EFT_INPUT_TIMEOUT |0011| "Timeout waiting for user input"| The card reader timed out while waiting for a user action. No further actions required.| +|EFT_USER_CANCELLED |0012| "TRANSACTION VOID" "User cancelled the transaction" |The current operation was cancelled by card holder. No further actions required.| +|EFT_SHARED_SECRET_INVALID| 001D| "Shared Secret invalid"| The card reader believes that the POS App has an incorrect shared secret. No financial operations will be possible (e.g. SALE, REFUND). Please type the correct shared secret into the POS App or contact technical support for further assistance.| +|EFT_SHARED_SECRET_AUTH |001E |"Authenticating POS"| The card reader is about to challenge the POS App for a correct shared secret. No further actions are required.| + | REPORT STATUS SPECIFIC| +|EFT_INVALID_SIGNATURE |0013| "TRANSACTION VOID"| The merchant indicated that the signature provided by the card holder was invalid. No further actions are required.| +|EFT_WAITING_CARD |0014| "Waiting for card" |The card reader is waiting for a card to be inserted into the chip reader or for a card to be swiped (only applies to card readers with external MSR). Insert or swipe a card to continue with the transaction.| +|EFT_CARD_INSERTED |0015| "Card detected" |`Currently not used`| +|EFT_APPLICATION_SELECTION |0016| "Waiting for application selection" |The card reader is waiting for the card holder to select a card application to be used for the transaction. The card holder must select an application for use (e.g. VISA, MASTERCARD, etc.) and should then press either the OK button to continue. Press the C/Cancel button to abort the transaction.| +|EFT_APPLICATION_CONFIRMATION| 0017| "Waiting for application confirmation"| The card reader is waiting for the card holder to confirm that the displayed card application should be used for the transaction. The card holder should press either the OK or the C/Cancel button.| +|EFT_AMOUNT_VALIDATION| 0018 |"Waiting for amount validation"| The card reader is waiting for the card holder to confirm that the amount presented is correct. The card holder should press either the OK or the C/Cancel button.| +|EFT_PIN_INPUT |0019| "Waiting for PIN entry"| The card reader is waiting for the card holder to enter his/her PIN. The card holder should enter his PIN and then press the OK button to continue. For PIN bypass press the OK button without entering any PIN digits (this will trigger signature fallback). Press the C/Cancel button to abort the transaction. Note: It is not possible to cancel this operation from the POS App.| +|EFT_MANUAL_CARD_INPUT |001A| "Waiting for manual card data"| `Currently not used`| +|EFT_WAITING_CARD_REMOVAL| 001B| "Waiting for card removal"| A card was detected in the card reader at the start of a transaction, presumably left there from a previous transaction. Please remove the card and restart the operation.| +|EFT_TIP_INPUT |001C| "Waiting for gratuity" |The card reader is waiting for the card holder to enter/confirm tip/gratuity information.| +|EFT_WAITING_SIGNATURE |001F| "Waiting for signature" |The card reader is waiting for confirmation from the merchant that the card holder signature is valid. The merchant should press either the Accepted or Declined/Cancel in the POS App. Pressing Cancel or OK on the card reader will not have any effect.| +|EFT_WAITING_HOST_CONNECT |0020| "Connecting to host"| The card reader is establishing a connection to the back end system. No further actions are required.| +|EFT_WAITING_HOST_SEND| 0021 |"Sending data to host" |The card reader is sending data to the back end system. No further actions are required.| +|EFT_WAITING_HOST_RECEIVE| 0022| "Waiting for data from host" |The card reader is waiting for data from to the back end system. No further actions are required.| +|EFT_WAITING_HOST_DISCONNECT| 0023| "Disconnecting from host"| The card reader is disconnecting from the back end system. No further actions are required.| +|EFT_PIN_INPUT_COMPLETED| 0024| "PIN entry completed"| PIN entry has been completed. No further actions required.| +|EFT_POS_CANCELLED |0025| "TRANSACTION VOID" |The current operation was cancelled by merchant. No further actions required.| +|EFT_REQUEST_INVALID| 0026| "Request invalid"| Card not allowed with this transaction type.| +|EFT_CARD_CANCELLED |0027| "TRANSACTION VOID"| The chip on the card cancelled the transaction. No further actions required.| +|EFT_CARD_BLOCKED |0028| |"CARD BLOCKED" |The card used in the transaction is blocked. Please retry the transaction with a non-blocked card.| +|EFT_REQUEST_AUTH_TIMEOUT |0029| "Request for authorisation timed out"| Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| +|EFT_REQUEST_PAYMENT_TIMEOUT| 002A| "Request for payment timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| +|EFT_RESPONSE_AUTH_TIMEOUT |002B| "Response to authorisation request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| +|EFT_RESPONSE_PAYMENT_TIMEOUT| 002C| "Response to payment request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. You MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once you have verified that the transaction did not go through then please make sure the phone/pc has an internet connection and then retry the operation.| +|EFT_ICC_CARD_SWIPED| 002D| "Please insert card in chip reader" |`Currently not used`| +|EFT_REMOVE_CARD |002E| "Remove the card from the reader" |`Currently not used`| +|EFT_SCANNER_IS_NOT_SUPPORTED| 002F| "This device does not have a scanner" |Bar-code scanner hardware is not present on this card reader. No further actions are required.| +|EFT_SCANNER_EVENT| 0030| "" |Bar-code data was just read with the bar-code scanner and returned to the POS App. No further actions are required.| +|EFT_BATTERY_TOO_LOW| 0031| "Operation cancelled, the battery is too low. Please charge."| An operation was started, but the battery charge level is too low to complete the operation. Please recharge the card reader.| +|EFT_ACCOUNT_TYPE_SELECTION| 0032| "Waiting for account type selection"| The card reader is waiting for the card holder to choose an account type for the transaction (i.e. default, credit, cheque/debit or savings).| \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosprocessing.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosprocessing.md new file mode 100644 index 0000000..ea2885b --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosprocessing.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 4 +id: iosprocessing +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our server: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md new file mode 100644 index 0000000..3368714 --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md @@ -0,0 +1,25 @@ +--- +sidebar_position: 2 +id: iosreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.2 +**Fixes**: +- Crash due to vector index out of bounds. + +## 4.0.1 +**Fixes**: + - Multi MID fix for INTERAC and POSTBRIDGE acquirers. + +## 4.0.0 +**Features**: + - Support for Multi MID and HiPro scanner fixes. + diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iossdkprocessing.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iossdkprocessing.md new file mode 100644 index 0000000..b614ac1 --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iossdkprocessing.md @@ -0,0 +1,373 @@ +--- +sidebar_position: 7 +id: iossdkprocessing +--- + + +# Integration Example + +## HandpointModule header + +**HandpointModule.h** + +````objectivec +#import "HandpointAll.h" + +@interface HandpointModule : NSObject + +- (instancetype)initWithSharedSecret:(NSString *)sharedSecret; + +- (void)saleWithAmount:(NSInteger)amount + currency:(NSString *)currency; + +- (void)refundWithAmount:(NSInteger)amount + currency:(NSString *)currency; + +- (void)saleReversalWithAmount:(NSInteger)amount + currency:(NSString *)currency + originalTransactionID:(NSString *)originalTransactionID; + +- (void)refundReversalWithAmount:(NSInteger)amount + currency:(NSString *)currency + originalTransactionID:(NSString *)originalTransactionID; + +- (void)connectToAddress:(NSString *)address; + +- (void)setLogLevel:(eLogLevel)logLevel; + +- (void)getDeviceLogs; + +- (void)getPendingTransaction; + +- (void)update; + +- (void)listDevices; + +@end +```` + +## HandpointModule + +**HandpointModule.m** + +````objectivec +#import "" +#import "HandpointModule.h" +#import "HeftRemoteDevice+SendableDevice.h" +#import "SDKEvent.h" +#import "ConnectionStatus.h" +#import "Currency.h" +#import "CDVInvokedUrlCommand+Arguments.h" +#import "StatusInfo.h" +#import "TransactionResult.h" + +typedef NS_ENUM(NSInteger, ConnectionStatus) +{ + ConnectionStatusNotConfigured, + ConnectionStatusConnected, + ConnectionStatusConnecting, + ConnectionStatusDisconnected, + ConnectionStatusDisconnecting, + ConnectionStatusInitializing +}; + +@interface HandpointModule () + +@property (nonatomic) HeftManager* manager; +@property (nonatomic, strong) id api; +@property (nonatomic) NSString *ssk; +@property (nonatomic) HeftRemoteDevice* preferredDevice; +@property (nonatomic) NSString *eventHandlerCallbackId; +@property (nonatomic) NSMutableDictionary *devices; + +@end + +@implementation HandpointModule + +- (instancetype)initWithSharedSecret:(NSString *)sharedSecret +{ + NSLog(@"\n\tpluginInitialize"); + self.manager = [HeftManager sharedManager]; + self.manager.delegate = self; + self.devices = [@{} mutableCopy]; + + [self fillDevicesFromConnectedCardReaders]; + + self.ssk = sharedSecret; +} + +- (void)saleWithAmount:(NSInteger)amount + currency:(NSString *)currency +{ + BOOL result = [self.api saleWithAmount:amount + currency:currency + cardholder:YES]; + + if (result == false) + { + //Do something + } +} + +- (void)refundWithAmount:(NSInteger)amount + currency:(NSString *)currency +{ + BOOL result = [self.api refundWithAmount:amount + currency:currency + cardholder:YES] + + if (result == false) + { + //Do something + } +} + +- (void)saleReversalWithAmount:(NSInteger)amount + currency:(NSString *)currency + originalTransactionID:(NSString *)originalTransactionID +{ + BOOL result = [self.api saleVoidWithAmount:amount + currency:currency + cardholder:YES + transaction:originalTransactionID]; + + if (result == false) + { + //Do something + } +} + +- (void)refundReversalWithAmount:(NSInteger)amount + currency:(NSString *)currency + originalTransactionID:(NSString *)originalTransactionID +{ + BOOL result = [self.api refundVoidWithAmount:amount + currency:currency + cardholder:YES + transaction:originalTransactionID]; + + if (result == false) + { + //Do something + } +} + +#pragma mark - Device Management + +- (void)connectToAddress:(NSString *)address +{ + HeftRemoteDevice *remoteDevice = self.devices[address]; + + if (remoteDevice) + { + BOOL isRemoteDeviceSameAsPreferred = self.preferredDevice && + [self.preferredDevice.address isEqualToString:remoteDevice.address]; + + // If we are already connected to this device, update shared secret + if (self.api && isRemoteDeviceSameAsPreferred) + { + // Already connected to device + } + else + { + self.preferredDevice = remoteDevice; + + [self.manager clientForDevice:remoteDevice + sharedSecret:self.ssk + delegate:self]; + } + + [self connectionStatusChanged:ConnectionStatusConnecting]; + } + else + { + NSLog(@"Can't connect. No device available. Have you searched?"); + } +} + +- (void)setLogLevel:(eLogLevel)logLevel +{ + [self.api logSetLevel:logLevel]; +} + +- (void)getDeviceLogs +{ + [self.api logGetInfo]; +} + +- (void)getPendingTransaction +{ + BOOL success = NO; + + if ([self.api isTransactionResultPending]) + { + success = [self.api retrievePendingTransaction]; + } + + if (success) + { + //... + } + else + { + //... + } +} + +- (void)update +{ + [self.api financeInit]; +} + +- (void)listDevices +{ + NSArray* devices = [self.manager connectedCardReaders]; + + /** + * A device can have four levels of connection: unpaired, paired, + * connected and connected in the SDK. + * + * Due to the nature of the iOS ExternalAccessory framework, + * devices that are already connected at an iOS level will not appear in a normal search, + * as they already appear through the "connectedCardReaders" array in the manager + * (Yeah, I know) + * + * So the "if" takes care of differentiating those two cases + * + * If we have device(s) connected we just go for those, otherwise, search. + */ + + if(devices.count) + { + //We have device(s) already connected, we skip the search. + for (HeftRemoteDevice *device in devices) + { + [self addDevice:device]; + } + + [self didDiscoverFinished]; + } + else + { + //We search and wait... + [self.manager startDiscovery]; + } +} + +# pragma mark - Callbacks + +- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice +{ + [self addDevice:newDevice]; +} + +- (void)didLostAccessoryDevice:(HeftRemoteDevice *)oldDevice +{ + [self removeDevice:oldDevice]; + + if(self.preferredDevice && self.preferredDevice.address == oldDevice.address) + { + [self connectionStatusChanged:ConnectionStatusDisconnected]; + + self.preferredDevice = nil; + } +} + +- (void)didDiscoverFinished +{ + [self fillDevicesFromConnectedCardReaders]; + + for (NSString *key in [self.devices allKeys]) + { + HeftRemoteDevice *device = self.devices[key]; + + if ([device.address isEqualToString:]) + { + //Do something with the device if it's the same one you expect. + break; + } + } +} + +- (void)didConnect:(id )client +{ + if(client) + { + self.api = client; + + [self connectionStatusChanged:ConnectionStatusConnected]; + } +} + +- (void)connectionStatusChanged:(ConnectionStatus)status +{ + //Here you get notified of connection status changes +} + +- (NSString *)stringFromConnectionStatus:(ConnectionStatus)status +{ + switch(status) + { + case ConnectionStatusNotConfigured: + return @"NotConfigured"; + case ConnectionStatusConnected: + return @"Connected"; + case ConnectionStatusConnecting: + return @"Connecting"; + case ConnectionStatusDisconnected: + return @"Disconnected"; + case ConnectionStatusDisconnecting: + return @"Diconnecting"; + case ConnectionStatusInitializing: + return @"Initializing"; + } +} + +- (void)responseStatus:(id )info +{ + //Here you'll get status updates during the transaction +} + +- (void)responseError:(id )info +{ + //Here if something went wrong +} + +- (void)responseFinanceStatus:(id )info +{ + //Here's the result of your transaction +} + +- (void)responseLogInfo:(id )info +{ + NSLog(@"\n\tresponseLogInfo: %@", info.status); +} + +- (void)requestSignature:(NSString *)receipt +{ + [self.api acceptSignature:YES]; +} + +- (void)addDevice:(HeftRemoteDevice *)device +{ + self.devices[device.address] = device; +} + +- (void)removeDevice:(HeftRemoteDevice *)device +{ + if (self.devices[device.address]) + { + [self.devices removeObjectForKey:device.address]; + } +} + +- (void)fillDevicesFromConnectedCardReaders +{ + for (HeftRemoteDevice *device in [self.manager connectedCardReaders]) + { + [self addDevice:device]; + } +} + +@end +```` diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iostransactions.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iostransactions.md new file mode 100644 index 0000000..a0fd2bb --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iostransactions.md @@ -0,0 +1,582 @@ +--- +sidebar_position: 8 +id: iostransactions +--- + + + +# Transaction Types + +## Sale{#2} + +`saleWithAmount` Method + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency ` Required
    *NSString* | 3 letter currency code in accordance to ISO4217| +| `options`
    *SaleOptions* | An object to store all the customization options for a sale.| + +**Code example** + +````objectivec +//If you just need a plain vanilla sale: +[api saleWithAmount:100 + currency:Currency.EUR.alpha]; + +//But you can customize your sale: +SaleOptions *options = [SaleOptions new]; +//Optionally +options.customerReference = @"Your customer reference"; +//If you need Multi MID / Custom merchant Authentication: +MerchantAuth *auth = [MerchantAuth new]; +Credential *cred = [Credential new]; +//Optionally +cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; +//Optionally +cred.mid = @"mid"; +//Optionally +cred.tid = @"tid"; +//Add as many credentials as Acquirers your merchant have agreements with +[auth add:cred]; +options.merchantAuth = auth; +//If you want to specify the budget period +//Only available for SureSwipe/Altech +//Here it's 3 months +options.divideByMonths = @"3"; + +[api saleWithAmount:100 + currency:Currency.EUR.alpha + options:options]; +```` + +**Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** +[**requestSignature**](iosevents.md#17) + +Invoked if card verification requires signature. +*** +[**responseFinanceStatus **](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + +## Sale And Tokenize Card{#4} + +`saleAndTokenizeCardWithAmount` Method + +A sale and tokenize operation initiates a payment operation with the payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    *NSString* | 3 letter currency code in accordance to ISO4217| +| `options`
    *SaleOptions* | An object to store all the customization options for a sale.| + +**Code example** + +````objectivec +//If you just need a plain vanilla sale tokenization: +[api saleAndTokenizeWithAmount:100 + currency:Currency.EUR.alpha]; + +//But you can customize your sale: +SaleOptions *options = [SaleOptions new]; +//Optionally +options.customerReference = @"Your customer reference"; +//If you need Multi MID / Custom merchant Authentication: +MerchantAuth *auth = [MerchantAuth new]; +Credential *cred = [Credential new]; +//Optionally +cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; +//Optionally +cred.mid = @"mid"; +//Optionally +cred.tid = @"tid"; +//Add as many credentials as Acquirers your merchant have agreements with +[auth add:cred]; +options.merchantAuth = auth; +//If you want to specify the budget period +//Only available for SureSwipe/Altech +//Here it's 3 months +options.divideByMonths = @"3"; + +[api saleAndTokenizeWithAmount:100 + currency:Currency.EUR.alpha + options:options]; +```` + +**Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**requestSignature**](iosevents.md#17) + +Invoked if card verification requires signature. +*** + +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + +## Sale Reversal{#3} + +`saleVoidWithAmount` Method + +Request a void of a previous sale transaction. Amount, currency and transactionID of the original sale must be sent as parameters. This operation reverts (if possible) a specific sale identified with a transaction id. Note that transactions can only be reversed the same day as when the transaction was made. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    *NSString* | 3 letter currency code in accordance to ISO4217 | +| `transaction` Required
    *NSString* | TransactionID of the sale transaction to be voided | +| `options`
    *Options* | An object to store all the customization options for this operation.| + +**Code example** + +```objectivec +//If you just need a plain vanilla sale reversal: +[api saleReversalWithAmount:100 + currency:Currency.EUR.alpha + transactionId:originalTransactionID + options:options]; + +//But you can customize your reversal: +Options *options = [Options new]; +//Optionally +options.customerReference = @"Your customer reference"; + +[api saleReversalWithAmount:100 + currency:Currency.EUR.alpha + transactionId:@"00000000-0000-0000-0000-000000000000" + options:options]; +``` + +**Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** +[**responseError **](iosevents.md#15) + +Invoked when an error response happens. +*** +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + +## Refund{#5} + +`refundWithAmount` Method + +A refund initiates a refund operation with the payment terminal. This operation moves funds from the merchant account to the cardholder's card. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    *NSString* | Currency of the charge| +| `transaction` Required
    *NSString* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
    *MerchantAuthOptions* | An object to store all the customization options for a refund.| + +**Code example** + +````objectivec +//If you just need a plain vanilla refund: +[api refundWithAmount:100 + currency:Currency.EUR.alpha + transaction:@"00000000-0000-0000-0000-000000000000"]; + +//But you can customize your sale: +MerchantAuthOptions *options = [MerchantAuthOptions new]; +//Optionally +options.customerReference = @"Your customer reference"; +//If you need Multi MID / Custom merchant Authentication: +MerchantAuth *auth = [MerchantAuth new]; +Credential *cred = [Credential new]; +//Optionally +cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; +//Optionally +cred.mid = @"mid"; +//Optionally +cred.tid = @"tid"; +//Add as many credentials as Acquirers your merchant have agreements with +[auth add:cred]; +options.merchantAuth = auth; + +[api refundWithAmount:100 + currency:Currency.EUR.alpha + transaction:@"00000000-0000-0000-0000-000000000000" + options:options]; +```` + +** Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + + +## Refund reversal{#6} + +`refundVoidWithAmount` Method + +Request a void of a previous refund transaction. Amount, currency and transactionID of the original refund must be sent as parameters. This operation reverts (if possible) a specific refund identified with a transaction id. Note that transactions can only be reversed the same day as when the transaction was made. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    *NSString* | 3 letter currency code in accordance to ISO4217| +| `transaction` Required
    *NSString* | TransactionID of the refund transaction to be voided| +| `options`
    *Options* | An object to store all the customization options for this operation.| + +**Code example** + +````objectivec +//If you just need a plain vanilla refund reversal: +[api refundReversalWithAmount:100 + currency:Currency.EUR.alpha + transactionId:originalTransactionID + options:options]; + +//But you can customize your sale: +Options *options = [Options new]; +//Optionally +options.customerReference = @"Your customer reference"; + +[api refundReversalWithAmount:100 + currency:Currency.EUR.alpha + transactionId:@"00000000-0000-0000-0000-000000000000" + options:options]; +```` + +** Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if the operation was successfully sent to device.| + +## Tokenize Card{#10} + +`tokenizeCard` Method + +Initiates a card tokenization operation with the payment terminal (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reference` Required
    *NSString* | string for customer reference| + + +**Code example** + +````objectivec +//Initiates a card tokenization operation. +[heftClient tokenizeCard]; +```` + + +** Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. + +*** + +[**requestSignature**](iosevents.md#17) + +Invoked if card verification requires signature. + +*** + +[**responseRecoveredTransactionStatus**](iosevents.md#44) + +Invoked when the card reader finishes processing the transaction. + +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + +## Accept signature{#7} + +`acceptSignature` Method + +A [*requestSignature*](iosevents.md#17) event is invoked during a transaction if signature verification is needed. The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureRequired lets the payment terminal know if the signature was approved (by passing YES to the function) or declined by the merchant (by passing NO to the function). + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `flag` Required
    *Boolean* | YES if signature is valid, NO otherwise| + + +**Code example** + +````objectivec +//acceptSignature: +//Inform the card reader if signature is valid or not +-(IBAction)accept +{ + [heftClient acceptSignature:YES]; +} +-(IBAction)decline +{ + [heftClient acceptSignature:NO]; +} +```` + +** Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** + +## Retrieve Pending Transaction{#8} + +`retrievePendingTransaction` Method + +Retrieving a pending transaction fetches a transaction result that was lost due to an unexpected disconnection between the payment terminal and the associated application. + +**Code example** + +````objectivec +//retrievePendingTransaction: +//Called when a pending transaction is discovered upon connecting to a specific card reader +- (void)didConnect:(id)client{ + heftClient = client; + + if(heftClient){ + if([heftClient isTransactionResultPending] == YES) { + // a pending transaction has been detected ... + // ... so, lets get it + [heftClient retrievePendingTransaction]; + } + } +} +```` + +** Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**responseRecoveredTransactionStatus**](iosevents.md#44) + +Invoked when the card reader has returned a recovered transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `YES` if operation starts successfully.| + +

    + +**Notes** + +***On starting a new transaction*** + +If a new transaction is started without fetching first a pending transaction result, then the pending transaction result will be discarded. +*** + +***User notifications while a transaction result is pending*** + +The payment terminal will not give any visible indication that a transaction result is pending. +*** + +***User notifications when fetching a pending transaction result*** + +The payment terminal will briefly display a message when a pending transaction result is recovered. +*** + +## Tip Adjustment{#9} + +`tipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +The tip adjustment method does not rely on a card reader and is therefore a separate method that must be initialized with a shared secret. The function is defined in the file HapiRemoteService.h +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
    *NSInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `transaction` Required
    *NSString* | TransactionID (GUID) of the original sale transaction to be adjusted| + + +**Code example** + +````objectivec +//First, you need to include the following dependency +#include "HapiRemoteService.h" + +//Second, the shared secret needs to be initialized +NSString* shared_secret = @"0102030405060708091011121314151617181920212223242526272829303132"; +BOOL result = setupHandpointApiConnection(shared_secret); + +//Third, you need to retrieve the unique transaction id of the original sale transaction you want to adjust. The below GUID is only an example and will result in a decline from the host if used for tip adjustment +NSString* transaction = @"d50af540-a1b0-11e6-85e6-07b2a5f091ec"; + +//Fourth, let's tip adjust a transaction for $10.00! +-(IBAction)tipAdjustment:(UIButton*) sender +{ + BOOL result = tipAdjustment(transaction, 1000, ^(TipAdjustmentStatus status) + { + if(status == TipAdjustmentAuthorised) { + + //Successfully adjusted! + + } + + else if(status == TipAdjustmentDeclined) { + + //Declined! + + } + + else if(status == TipAdjustmentFailed) { + + //Timeout! + + } + }); +} +```` + +**Returns** + +Result of the tip adjustment transaction, possible values : + +| Parameter | Notes | +| ----------- | ----------- | +| **status**| - **TipAdjustmentAuthorised** (tip adjustment approved by the processor)
    - **TipAdjustmentFailed** (system error or timeout)
    - **TipAdjustmentDeclined** (tip adjustment declined by the processor)| + + + + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. diff --git a/ios_versioned_sidebars/version-iOS SDK 4.0.2-sidebars.json b/ios_versioned_sidebars/version-iOS SDK 4.0.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/ios_versioned_sidebars/version-iOS SDK 4.0.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/ios_versions.json b/ios_versions.json index 4c1ba60..24dc27b 100644 --- a/ios_versions.json +++ b/ios_versions.json @@ -1,4 +1,5 @@ [ + "iOS SDK 4.0.2", "iOS SDK 4.0.1", "iOS SDK 4.0.0" ] From a6858619b39452c826b7ef49d51d16dc4d389d6b Mon Sep 17 00:00:00 2001 From: Raul Carrasco Date: Fri, 23 May 2025 20:09:25 +0200 Subject: [PATCH 098/115] docs: SDK-3854_1 Update README (#128) --- README.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1c34961..d4f8ebe 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,78 @@ This is the source code for the [Handpoint Documentation website](https://develo ## Local Development -### Requirements +### Requirements -Docusaurus is essentially a set of npm packages. If you want to build the site locally, you will need to have [Node.js](https://nodejs.org/en/) version 18 or above installed. +To build the site locally, you will need to have the following installed: +- [Node.js](https://nodejs.org/en/) version 18 or above +- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable) +- [Docusaurus](https://docusaurus.io/) -You'll also have to install [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable). +### Installing Node 18 -### Installation +If you don't have Node 18 installed, you can use **Node Version Manager**, also known as [nvm](https://github.com/nvm-sh/nvm) to install it. Nvm is a bash script that allows you to manage multiple versions of Node.js on your machine. It is a great tool for developers who need to switch between different versions of Node.js for different projects. -To install the dependencies, run: +To install nvm, you can use the following command: + +```shell +brew install nvm +``` + +Once installed, you should create NVM's working directory if it doesn't exist: + +```shell +mkdir ~/.nvm +``` + +Additionally, add the following lines to your shell profile e.g. ~/.profile or ~/.zshrc: ```bash +export NVM_DIR="$HOME/.nvm" +[ -s "/usr/local/opt/nvm/nvm.sh" ] && \. "/usr/local/opt/nvm/nvm.sh" # This loads nvm +[ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/usr/local/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion +``` + +After installing nvm, you can install Node 18 by running the following command: + +```shell +nvm install 18 +``` + +To verify it was installed correctly, you can check the version of Node.js by running: + +```shell +node -v +``` + +Once Node 18 is installed, you can set it as the default version by running: + +```shell +nvm alias default 18 +``` + +### Installing NPM + +NPM (Node Package Manager) is included with Node.js, so you don't need to install it separately. However, if you want to update it to the latest version, you can run: + +```shell +npm update -g npm +``` + +### Installing Yarn + +Yarn is a package manager used to manage dependencies in JavaScript projects. It is an alternative to npm and is known for its speed and reliability. + +To install Yarn, you can use the following command: + +```shell +npm install --global yarn +``` + +### Install dependencies with Yarn + +To install the project dependencies, move to the root folder of the project and run: + +```shell yarn install ``` @@ -26,7 +87,37 @@ In the root folder we must execute the following commands: yarn start ``` -This command starts a local development server and opens up a browser window (by default localhost:3000). Most changes are reflected live without having to restart the server. +This command starts a local development server and opens up a browser window (by default **localhost:3000**). Most changes are reflected live without having to restart the server. + +Closing the browser window or the tab will stop the server. You can also stop the server by pressing `Ctrl + C` in the terminal. + +## How the documentation is organized + +Documentation is mainly organized in folders, classified by every SDK type available for Handpoint integrators: + +- `android`: Android SDK +- `express`: Express SDK +- `ios`: iOS SDK +- `javascript`: Javascript SDK +- `restapi`: REST API +- `windows`: Windows SDK + +Every one of the above folders is replicated in their own `versioned_docs` and `versioned_sidebars` folders. This is where the versioned documentation is stored. + +For example, the Android SDK version 6.7.0 related documentation can be found in two places: + +- `android_versioned_docs/version-Android SDK 6.7.0`: Documentation. +- `android_versioned_sidebars/version-Android SDK 6.7.0-sidebars.json`: Sidebar configuration. + +Additionally to these folders, there are other folders that are used for the website: + +- `blog`: Blog entries. +- `docs`: Documentation not directly related with SDKs (for example FAQs and introduction). +- `src`: Source code for the website (CSS, search bar, etc). +- `static`: Static files (images, etc). +- `txnfeedapi`: Transaction feed API documentation. +- `versioned_docs`: Versioned documentation of the tutorial. +- `versioned_sidebars`: Versioned sidebar configuration of the tutorial. ## Generate a new SDK version Generate a new SDK version will autogenerate a folder with the docs that are currently in the selected folder. From 7f8063511fededf045bf3fb3f3f0a21dff3fd354 Mon Sep 17 00:00:00 2001 From: Raul Carrasco Date: Mon, 9 Jun 2025 18:54:24 +0200 Subject: [PATCH 099/115] docs: SDK-3854_2 Add info about Docusaurus (#131) --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d4f8ebe..30fa995 100644 --- a/README.md +++ b/README.md @@ -119,19 +119,56 @@ Additionally to these folders, there are other folders that are used for the web - `versioned_docs`: Versioned documentation of the tutorial. - `versioned_sidebars`: Versioned sidebar configuration of the tutorial. +## How to use Docusaurus with NPM + +Docusaurus is a static site generator that allows you to create documentation websites easily. It uses React and Markdown to create a fast and customizable documentation site. + +To use Docusaurus, just run the following command in the root folder of the project: + +```console +npm run docusaurus +``` + +### Docusaurus commands and options + +```console +Usage: [options] + +Options: + -V, --version output the version number + -h, --help display help for command + +Commands: + build [options] [siteDir] Build website. + swizzle [options] [themeName] [componentName] [siteDir] Wraps or ejects the original theme files into website folder for customization. + deploy [options] [siteDir] Deploy website to GitHub pages. + start [options] [siteDir] Start the development server. + serve [options] [siteDir] Serve website locally. + clear [siteDir] Remove build artifacts. + write-translations [options] [siteDir] Extract required translations of your site. + write-heading-ids [options] [siteDir] [files...] Generate heading ids in Markdown content. + docs:version Tag a new docs version + docs:version:ios Tag a new docs version (ios) + docs:version:javascript Tag a new docs version (javascript) + docs:version:restapi Tag a new docs version (restapi) + docs:version:windows Tag a new docs version (windows) + docs:version:express Tag a new docs version (express) + docs:version:android Tag a new docs version (android) +``` + ## Generate a new SDK version Generate a new SDK version will autogenerate a folder with the docs that are currently in the selected folder. -Command to create a new version of Android SDK (e.g. version 6.8.0) +Command to create a new version of Android SDK (e.g. version 7.1009.5) ```console -npm run docusaurus docs:version:android "Android SDK 6.8.0" +npm run docusaurus docs:version:android "Android SDK 7.1009.5" ``` -`android` represents the folder where Android docs are. `"Android SDK 6.8.0"` is the name of the new version, it will appear as is on the documentation website -Automatically, it will create the new folder for this version (version-Android SDK 6.8.0) in `android_versioned_docs`. +`android` represents the folder where Android docs are. `"Android SDK 7.1009.5"` is the name of the new version, it will appear as is on the documentation website +Automatically, it will create the new folder for this version (version-Android SDK 7.1009.5) in `android_versioned_docs`. -**To see it published you have to stop docusaurus and start it again** +**To see it published you will have to restart docusaurus.** ## Deployment From d931c1bb290b7116e3523180ff17ab950690dece Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Fri, 20 Jun 2025 15:40:17 +0200 Subject: [PATCH 100/115] SDK-3887 (#132) feat: Adding Android SDK 7.1010.1 version --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 174 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 444 ++++ .../androidtransactions.md | 2027 +++++++++++++++++ ...version-Android SDK 7.1010.1-sidebars.json | 8 + android_versions.json | 1 + 12 files changed, 6210 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.1-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.1/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
    [*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
    [*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
    [*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
    *String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
    [*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
    [*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
    [*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
    [*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
    [*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
    *String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.1/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
    *List ``* | A list containing the supported card brands| + +

    + +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
    [*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
    *ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
    [*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
    [*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
    [*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
    [*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
    [*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
    [*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
    [*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
    List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
    [*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
    [*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
    *HardwareStatus* | New status of the hardware.| +| `device` Required
    [*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
    *String* | Message to display| +| `dismissible` Required
    *Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
    *int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
    *String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
    [*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
    *String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
    [*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
    [*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
    [*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
    *String* | The text of the report| +| `status` Required
    [*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
    [*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
    [*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
    [*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
    [*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
    [*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
    [*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
    *BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
    *String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.1/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
    *Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
    *Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidintegrationguide.md new file mode 100644 index 0000000..f175114 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

    +android.enableJetifier=true

    +android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md new file mode 100644 index 0000000..0445acb --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md @@ -0,0 +1,174 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
    +
    +
    +

    Android SDK

    +
    +
    + +
    + +
    +
    + +

    + +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

    + +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

    +android.enableJetifier=true

    +android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
    *String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
    *String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
    *String* | Acquirer response code.| +| `balance`
    [*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
    *String* | Used to split payments over a period of months.| +| `cardEntryType`
    [*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
    *String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
    [*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
    *String* | Token representing the PAN of the card.| +| `chipTransactionReport`
    *String* | Full report of the card EMV parameters.| +| `currency`
    [*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
    *String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
    *String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
    [*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
    *String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
    *Date* | Time of the transaction.| +| `efttransactionID`
    *String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
    *String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
    *String* | Expiry date of the card used for the operation.| +| `finStatus`
    [*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
    *String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
    *String* | Response code from the card issuer.| +| `maskedCardNumber`
    *String* | Masked card number of the card used for the operation.| +| `merchantAddress`
    *String* | Merchant Address.| +| `merchantName`
    *String* | Merchant Name.| +| `merchantReceipt`
    *String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
    [*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
    *String* | Merchant Identifier.| +| `originalEFTTransactionID`
    *String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
    [*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
    *Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
    *BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
    *String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
    *String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
    *String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
    [*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
    *String* | Terminal Identifier.| +| `tipAmount`
    *BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
    *Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
    *BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
    *String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
    *String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
    *String* | Transaction Verification Results (EMV tag 95).| +| `type`
    [*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
    *String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
    [*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
    *Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
    *Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
    *String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
    *Integer* | The amount balance | +| `currency`
    *Currency*| The balance currency | +| `sign`
    [*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
    *String* | Token representing the card number| +| `expiryDate`
    *String*| Expiration date of the card| +| `tenderType`
    [*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
    *CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
    *String* | A name to identify the device| +| `address` Required
    *String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
    *UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
    [*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
    *String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
    *int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
    *String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
    *Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
    *Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
    *String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
    *String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
    *String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
    *String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
    *String* | Gets the status of the payment terminal external power| +| `ApplicationName`
    *String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
    *String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
    | Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
    | The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
    | The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
    | The `printReceipt` operation was successful.| +| `FAILED`
    | Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
    | The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
    | A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
    | The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
    | The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
    | The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
    *String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
    [*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
    *Context* | The Android context.| +| `handpointCredentials` Required
    [*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
    *String* | Gets the default shared secret in use.| +| `LogLevel`
    [*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
    *boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
    *String* | Gets the current SDK version.| +| `isTransactionResultPending`
    *boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
    *boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
    [*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
    *List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
    [*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
    [*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
    *String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
    *String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
    *String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
    *String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
    [*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
    *String* | An arbitrary string containing any information/data. Max length 250 characters
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
    *String* | An arbitrary string containing any information/data. Max length 250 characters
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
    *String* | An arbitrary string containing any information/data. Max length 250 characters
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
    *String* | An arbitrary string containing any information/data. Max length 250 characters
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
    *String* | An arbitrary string containing any information/data. Max length 250 characters
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
    *String* | first and last name of the recipient of the funds| +| `countryCode` Required
    *CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
    [*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
    *Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
    [*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
    [*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
    [*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
    [*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
    [*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
    *boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
    *String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
    *String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
    *String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
    *String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
    [*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
    [*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
    [*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
    *Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
    *Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
    *Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
    [*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
    [*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
    [*Currency*](#13) | The currency to filter the transactions| +| `startDate`
    *String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
    *String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
    *String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
    *List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
    *String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
    [*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
    *Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
    *Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
    [*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
    *Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
    [*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
    [*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
    *String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
    *String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
    [*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
    *Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
    *Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
    [*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
    *Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
    [*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
    *boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
    *boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
    *Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
    *Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
    *boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
    *boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
    *int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
    *String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
    *Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
    [*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
    [*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
    *Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
    *String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
    [*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
    *String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
    *BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
    *BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
    *String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
    *List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
    *Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
    *Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
    *String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md new file mode 100644 index 0000000..3a8b62e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md @@ -0,0 +1,444 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md new file mode 100644 index 0000000..a074b1e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md @@ -0,0 +1,2027 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
    [*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
    [*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
    *String* | Id of the original sale transaction| +| `options`
    [*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
    *String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
    [*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
    *String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
    *String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
    *String* | transaction id of the original refund| +| `options`
    [*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
    *String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
    *String* | Id of the original sale transaction.| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
    [*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
    *Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
    *BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
    *String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
    - **FinancialStatus.FAILED** (system error or timeout)
    - **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
    [*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
    [*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
    [*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
    *String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
    [*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
    *BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
    [*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
    *String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
    [*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

    When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
    *String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
    [*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.1-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 044037b..7d073a9 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.1", "Android SDK 7.1009.5", "Android SDK 7.1008.6", "Android SDK 7.1008.5", From 65182ee74c6b80350fab7725b1e3f8eb61d5d45b Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Tue, 24 Jun 2025 12:39:19 +0200 Subject: [PATCH 101/115] SDK-3886 (#133) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ➕ A8900 ➕ iOS 4.0.2 ➖ manual 'entry transaction' references under MoTo ➖ HiLite Logs gathering info (not available for Prod devices) --- .../androidintroduction.md | 9 ++- .../androidintroduction.md | 8 +- docusaurus.config.js | 59 +++++++++++++-- .../version-iOS SDK 4.0.2/iosobjects.md | 73 ++++--------------- src/pages/cpdocs.js | 34 ++++++--- 5 files changed, 98 insertions(+), 85 deletions(-) diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md index 0445acb..fafcc67 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidintroduction.md @@ -44,10 +44,11 @@ We take care of PCI compliance so you can be kept out of PCI scope. The Handpoin ### SDK distribution -The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. -- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. -- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1009.5-RC.16-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1009.5** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md index 0445acb..71f733b 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidintroduction.md @@ -44,11 +44,11 @@ We take care of PCI compliance so you can be kept out of PCI scope. The Handpoin ### SDK distribution -The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. -- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. -- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.1-RC.0-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.1** +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** diff --git a/docusaurus.config.js b/docusaurus.config.js index e788345..36102ac 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -175,13 +175,56 @@ module.exports = { }, }, }, - themes:[ - ['@easyops-cn/docusaurus-search-local', - {indexBlog:false, - indexPages:false, - indexDocs:true, - docsDir:['android','ios','windows','javascript','restapi','express'], - docsRouteBasePath:['android','ios','windows','javascript','restapi','express']}]], + themes: [ + ['@easyops-cn/docusaurus-search-local', { + id: 'search-android', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'android', + docsRouteBasePath: 'android', + }], + ['@easyops-cn/docusaurus-search-local', { + id: 'search-ios', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'ios', + docsRouteBasePath: 'ios', + }], + ['@easyops-cn/docusaurus-search-local', { + id: 'search-windows', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'windows', + docsRouteBasePath: 'windows', + }], + ['@easyops-cn/docusaurus-search-local', { + id: 'search-javascript', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'javascript', + docsRouteBasePath: 'javascript', + }], + ['@easyops-cn/docusaurus-search-local', { + id: 'search-restapi', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'restapi', + docsRouteBasePath: 'restapi', + }], + ['@easyops-cn/docusaurus-search-local', { + id: 'search-express', + indexBlog: false, + indexPages: false, + indexDocs: true, + docsDir: 'express', + docsRouteBasePath: 'express', + }], +], presets: [ [ '@docusaurus/preset-classic', @@ -300,4 +343,4 @@ module.exports = { ], ] -}; +}; \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md index ce8d0a0..225b5c7 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md @@ -53,7 +53,7 @@ The HeftManager is used for discovering and connecting to devices as well as cre `HeftClient` Object -High level interface for the API. HeftClient handles the communication between your application and the payment terminal. The HeftClient object also stores information about the payment terminal in the mpedInfo dictionary. Device Log operations are also implemented in HeftClient. To create a new HeftClient object the clientForDevice method is called from an instance of the HeftManager. Transaction and log requests (and the acceptSignature response) are done by calling HeftClient methods with the relevant input. The library reports the status of the requests by calling delegates of the HeftStatusReportDelegate protocol. +High level interface for the API. HeftClient handles the communication between your application and the payment terminal. The HeftClient object also stores information about the payment terminal in the mpedInfo dictionary. To create a new HeftClient object the clientForDevice method is called from an instance of the HeftManager. Transaction requests (and the acceptSignature response) are done by calling HeftClient methods with the relevant input. The library reports the status of the requests by calling delegates of the HeftStatusReportDelegate protocol. **Properties** @@ -189,21 +189,6 @@ High level interface for the API. HeftClient handles the communication between y - (BOOL)financeInit; *** -[**logSetLevel**](iosdevicemanagement.md#33) - -- (BOOL)logSetLevel:(eLogLevel)level; -*** - -[**logReset**](iosdevicemanagement.md#35) - -- (BOOL)logReset; -*** - -[**logGetInfo**](iosdevicemanagement.md#34) - -- (BOOL)logGetInfo; -*** - [**acceptSignature**](iostransactions.md#7) - (void)acceptSignature:(BOOL)flag; @@ -280,11 +265,6 @@ Notifications sent by the SDK on various events - connected to device, request s - (void)responseFinanceStatus:(id-FinanceResponseInfo)info; *** -[**responseLogInfo**](iosevents.md#43) - -- (void)responseLogInfo:(id-LogInfo)info; -*** - [**requestSignature**](iosevents.md#17) - (void)requestSignature:(NSString*)receipt; @@ -342,7 +322,7 @@ A FinanceResponseInfo is passed to the responseFinanceStatus delegate at the end | Property | Description | | ----------- | ----------- | | `financialResult`
    *NSInteger* | A numerical representation of a financial status result.
    EFT_FINANC_STATUS_UNDEFINED 0x00
    EFT_FINANC_STATUS_TRANS_APPROVED 0x01
    EFT_FINANC_STATUS_TRANS_DECLINED 0x02
    EFT_FINANC_STATUS_TRANS_PROCESSED 0x03
    EFT_FINANC_STATUS_TRANS_NOT_PROCESSED 0x04
    EFT_FINANC_STATUS_TRANS_CANCELLED 0x05| -| `isRestarting`
    *BOOL* | Indicates whether the card reader is about to restart or not (usually triggered after a software update is received).If a restart is imminent then you have 2 seconds to start fetching the logs (before the card reader restarts). After fetching the logs you should disconnect from the card reader and wait for it to be visible again.| +| `isRestarting`
    *BOOL* | Indicates whether the card reader is about to restart or not (usually triggered after a software update is received).If a restart is imminent then you should disconnect from the card reader and wait for it to be visible again.| | `authorisedAmount`
    *NSInteger* | Amount in the smallest unit of the currency - For example 1000 in case the CurrencyCode is "0826" (GBP) corresponds to 10.00 pounds.| | `transactionId`
    *NSString* | The id of the current transaction.| | `customerReceipt`
    *NSString* | Customer receipt in html format.| @@ -403,30 +383,6 @@ This object contains information about the scanner operation. | `status`
    [*Status as NSString*](#45) | Financial transaction status.| | `xml`
    [*XML as NSDictionary*](#46) | XML details from the payment terminal.| -## LogInfo{#28} - -`LogInfo` Object - -A LogInfo object is passed to the ResponseLogInfo delegate when logs have been downloaded from the payment terminal. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `statusCode`
    *int* | A numerical representation of the status.| -| `status`
    [*Status as NSString*](#45) | Financial transaction status.| -| `xml`
    [*XML as NSDictionary*](#46) | XML details from the payment terminal.| -| `log`
    *NSString* | String containing the logging information.| - -## eLogLevel{#13} - -`eLogLevel` Enum - -An enum describing the different levels of logging used in the SDK and in the payment terminal. - -**Possible values** - -`eLogNone` `eLogError` `eLogInfo` `eLogFull` `eLogDebug` ## Transaction Details{#46} @@ -710,19 +666,18 @@ All values are in hex in the following table. | Status ID | Value | StatusMessage| Details | | ----------- | ----------- |----------- | ----------- | | EFT_SUCCESS | 0001| One of the following: "" (an empty string) "AUTH CODE #" "REFUND ACCEPTED" "REVERSAL ACCEPTED"|Operation completed successfully. No further actions required.| -| EFT_INVALID_DATA | 0002|"Invalid data"|Invalid COMMAND request object, from the POS App, at the start of an operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_PROCESSING_ERROR |0003| "Processing error"| An unexpected error occurred during processing. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| +| EFT_INVALID_DATA | 0002|"Invalid data"|Invalid COMMAND request object, from the POS App, at the start of an operation. Please retry the operation. If the issue persists please contact technical support and provide any logs gathered from the POS for the request being sent.| +|EFT_PROCESSING_ERROR |0003| "Processing error"| An unexpected error occurred during processing. Please retry the operation. If the issue persists please contact technical support and provide transaction information such as transaction id, timestamp and device serial number.| |EFT_COMMAND_NOT_ALLOWED| 0004| "Command not allowed"| The card reader is currently busy processing another command. Please retry the operation once the current operation has completed.|| |EFT_NOT_INITIALISED |0005 |"Device is not initialized"| The current operation can’t be completed because there is a pending software update that must be applied before processing can continue. Please retry the operation after the card reader has restarted itself.| -|EFT_CONNECT_TIMEOUT |0006 |"Connection time out detected"| The back end connection timed out during an update. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_CONNECT_ERROR |0007 |"Connection error" |It was not possible to establish a connection to the back end system during an update operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_SENDING_ERROR |0008 |"Send error" |A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| -|EFT_RECEIVING_ERROR |0009| "Receiving error"| A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| -|EFT_NO_DATA_AVAILABLE |000A| "No data available"| The POS App is trying to fetch the card reader log file but there is no data stored in the log file. If logs are required then please set the log level to an appropriate value and retry the operation.| +|EFT_CONNECT_TIMEOUT |0006 |"Connection time out detected"| The back end connection timed out during an update. Please retry the operation. If the issue persists please contact technical support.| +|EFT_CONNECT_ERROR |0007 |"Connection error" |It was not possible to establish a connection to the back end system during an update operation. Please retry the operation. If the issue persists please contact technical support.| +|EFT_SENDING_ERROR |0008 |"Send error" |A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Once verified please retry the operation.| +|EFT_RECEIVING_ERROR |0009| "Receiving error"| A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Once verified please retry the operation.| |EFT_TRANS_NOT_ALLOWED |000B| "Transaction not allowed"| `Currently not used`| |EFT_UNSUPPORTED_CURRENCY| 000C| "Currency not supported"| A currency has been selected that the card reader has not been configured for. Please select the correct currency and retry the operation. Alternatively, please contact technical support and ask for the specific currency to be supported.| -|EFT_NO_HOST_AVAILABLE| 000D |"No host configuration found"| An update was initiated but the card reader could not find any host information for the back end system, even though it otherwise contains valid configuration. This is indicative of an invalid `hostBlock` block with in the `HostList` block in this device configuration, which was placed on the card reader during a previous update. Please contact technical support and provide card reader logs and ask for a replacement device. The card reader will be unable to update itself and must be replaced.| -|EFT_CARD_READER_ERROR |000E |"Card reader error"| Error detected in the chip reader or the magnetic stripe reader. Please retry the operation. If the issue persists please contact technical support and provide them with the card reader logs as well as asking for a replacement reader.| +|EFT_NO_HOST_AVAILABLE| 000D |"No host configuration found"| An update was initiated but the card reader could not find any host information for the back end system, even though it otherwise contains valid configuration. This is indicative of an invalid `hostBlock` block with in the `HostList` block in this device configuration, which was placed on the card reader during a previous update. Please contact technical support and ask for a replacement device. The card reader will be unable to update itself and must be replaced.| +|EFT_CARD_READER_ERROR |000E |"Card reader error"| Error detected in the chip reader or the magnetic stripe reader. Please retry the operation. If the issue persists please contact technical support and ask for a replacement reader.| |EFT_CARD_READING_FAILED| 000F| "Failed to read card data"| The card reader could not read any data from the card. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| |EFT_INVALID_CARD |0010 |"INVALID CARD" |The card reader detected invalid card data. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| |EFT_INPUT_TIMEOUT |0011| "Timeout waiting for user input"| The card reader timed out while waiting for a user action. No further actions required.| @@ -750,10 +705,10 @@ All values are in hex in the following table. |EFT_REQUEST_INVALID| 0026| "Request invalid"| Card not allowed with this transaction type.| |EFT_CARD_CANCELLED |0027| "TRANSACTION VOID"| The chip on the card cancelled the transaction. No further actions required.| |EFT_CARD_BLOCKED |0028| |"CARD BLOCKED" |The card used in the transaction is blocked. Please retry the transaction with a non-blocked card.| -|EFT_REQUEST_AUTH_TIMEOUT |0029| "Request for authorisation timed out"| Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_REQUEST_PAYMENT_TIMEOUT| 002A| "Request for payment timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_RESPONSE_AUTH_TIMEOUT |002B| "Response to authorisation request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_RESPONSE_PAYMENT_TIMEOUT| 002C| "Response to payment request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. You MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once you have verified that the transaction did not go through then please make sure the phone/pc has an internet connection and then retry the operation.| +|EFT_REQUEST_AUTH_TIMEOUT |0029| "Request for authorisation timed out"| Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support.| +|EFT_REQUEST_PAYMENT_TIMEOUT| 002A| "Request for payment timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support.| +|EFT_RESPONSE_AUTH_TIMEOUT |002B| "Response to authorisation request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support.| +|EFT_RESPONSE_PAYMENT_TIMEOUT| 002C| "Response to payment request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. You MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Once you have verified that the transaction did not go through then please make sure the phone/pc has an internet connection and then retry the operation.| |EFT_ICC_CARD_SWIPED| 002D| "Please insert card in chip reader" |`Currently not used`| |EFT_REMOVE_CARD |002E| "Remove the card from the reader" |`Currently not used`| |EFT_SCANNER_IS_NOT_SUPPORTED| 002F| "This device does not have a scanner" |Bar-code scanner hardware is not present on this card reader. No further actions are required.| diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 297c73e..3eb8d3a 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -267,7 +267,7 @@ function Standalone() {

    YRviaCld0sYR}UypZ_fk!SO~+o}Ycp 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 Date: Thu, 8 May 2025 12:17:30 +0200 Subject: [PATCH 094/115] rolled back acquirer's ENUM (#122) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space --- .../version-iOS SDK 4.0.1/iosintegration.md | 38 ++++++++----------- .../version-REST API 2.20.0/restendpoints.md | 5 +-- .../version-REST API 2.20.0/restobjects.md | 2 +- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md index f75cdeb..1b6f84f 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md @@ -6,10 +6,9 @@ id: iosintegration # Integration Guide -**The SDK supports the following connection methods:** +**The SDK supports the following connection method:** -1. **[Bluetooth (HiLite)](#filesiniOSSDK)** -2. **[Lightning (HiPro)](#filesiniOSSDK)** +**[Bluetooth (HiLite)](#filesiniOSSDK)** ## Files in iOS SDK {#filesiniOSSDK} @@ -20,7 +19,7 @@ id: iosintegration ### If you're using the framework/Carthage: -- ** HandpointSDK.h**: #import this header file into your classes. +- **HandpointSDK.h**: #import this header file into your classes. - **HandpointSDK.framework**: The SDK library. The SDK also includes a simulator, a library configured to simulate a payment terminal - intended for early development of an user interface. To use it, just link the libheft.a file in the HeftSimulatorLibrary folder, instead of the actual SDK library. @@ -56,20 +55,19 @@ The SDK also includes a simulator, a library configured to simulate a payment te Any application using the Handpoint SDK should follow these steps: -1. Define a class that implements the** HeftDiscoveryDelegate **protocol. +1. Define a class that implements the **HeftDiscoveryDelegate** protocol. This class defines the behavior of the app when discovery related events are received from the SDK. 2. Define a class that implements the **HeftStatusReportDelegate** protocol (it can be the same as above). This class defines the behavior of the app when connection and transaction related events are received from the SDK 3. Get a reference to the HeftManager singleton and assign your HeftDiscoveryDelegate instance as delegate. -4. If device is available through BT connection, start the discovery process by calling the** startDiscovery** function of the HeftManager and recover a list of the discovered devices by calling the **connectedCardReaders **function of the HeftManager. -5. If device is using a Lightning connector (HiPro devices), recover the device by directly calling the **connectedCardReaders** function of the HeftManager. -6. Connect to a device by calling the **clientForDevice** function of the HeftManager. -7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. -8. From this point, start processing transactions and have fun! +4. Start the discovery process by calling the **startDiscovery** function of the HeftManager and recover a list of the discovered devices by calling the **connectedCardReaders** function of the HeftManager. +5. Connect to a device by calling the **clientForDevice** function of the HeftManager. +6. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. +7. From this point, start processing transactions and have fun! ## Usage details -1. Define a class that implements the ** HeftDiscoveryDelegate **protocol. +1. Define a class that implements the **HeftDiscoveryDelegate** protocol. This class will define the behavior of the application when discovery related events are received from the SDK. ````objectivec @@ -77,7 +75,7 @@ This class will define the behavior of the application when discovery related ev @implementation MyDiscoveryDelegate ```` -2. Define a class that implements the** HeftStatusReportDelegate **protocol (it can be the same as above). +2. Define a class that implements the **HeftStatusReportDelegate** protocol (it can be the same as above). This class will define the behavior of the application when connection and transaction related events are received from the SDK. ````objectivec @@ -119,13 +117,7 @@ When the discovery process is finished, the **didDiscoverFinished** function of } ```` -5. If device is using a Lightning connection (HiPro devices), skip the previous step and recover the device by directly calling the **connectedCardReaders** function of the HeftManager. - -````objectivec -HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstObject]; -```` - -6. Connect to a device by calling the **clientForDevice** function of the HeftManager. +5. Connect to a device by calling the **clientForDevice** function of the HeftManager. * Expected parameters of this function are: @@ -144,7 +136,7 @@ HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstOb delegate:myStatusReportDelegate]; ```` -7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. Function receives as parameter a HeftClient object, whose reference must be stored since it is the communication bridge to the device we have connected to. +6. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. Function receives as parameter a HeftClient object, whose reference must be stored since it is the communication bridge to the device we have connected to. ```` objectivec - (void)didConnect:(id )client @@ -153,13 +145,13 @@ HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstOb } ```` -8. Once connected to the card reader, transactions can be started through the HeftClient object. For example, the next code starts a sale of 100 GBP: +7. Once connected to the card reader, transactions can be started through the HeftClient object. For example, the next code starts a sale of 100 GBP: ````objectivec [self.heftClient saleWithAmount:100 currency:@"GBP" cardholder:YES]; ```` -9. When a transaction has been initiated (f.ex saleWithAmount), the HeftClient alerts the HeftStatusReportDelegate object by invoking **responseStatus** during the process and **responceFinanceStatus** when the process has finished. +8. When a transaction has been initiated (E.g saleWithAmount), the HeftClient alerts the HeftStatusReportDelegate object by invoking **responseStatus** during the process and **responceFinanceStatus** when the process has finished. ````objectivec - (void)responseStatus:(id)info @@ -178,7 +170,7 @@ HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstOb } ```` -10. In case you are using the **SDK simulator**, the behavior changes according to the amount of the transaction: +9. In case you are using the **SDK simulator**, the behavior changes according to the amount of the transaction: | **Amount** | **Behavior** | | ----------- | ----------- | diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md index baff356..163cdf3 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restendpoints.md @@ -534,9 +534,8 @@ Common Response Codes --- :::caution -For the Commands to work properly, the Handpoint Payment App needs to be set to **Integrated Mode.**
    -Otherwise the response might be a **202 Accepted**, but the command will **not** be executed by the App.
    -As a workaround you can use the [`pingDevice` operation](restobjects#operation-types-description) +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
    +If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. ::: ### Set Unattended Mode diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md index 1ed8d94..285a772 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md @@ -15,7 +15,7 @@ An enum representing the supported acquirers for merchant authentication. **Possible values** -`AMEX` `TEYA|BORGUN` `OMNIPAY` `POSTBRIDGE` `TNS` `TSYS` `VANTIV|WORLDPAY` `SANDBOX` `TILLED` +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` ## Balance From f7cff17f01370b09da7632f568985b2c45d50c80 Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Fri, 9 May 2025 10:15:19 +0200 Subject: [PATCH 095/115] removed HiPro reference from iOS SDK (#123) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space From f21ee350aa972a2299af28916d003bb903230e1f Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Fri, 9 May 2025 14:37:29 +0200 Subject: [PATCH 096/115] Add tokenize parameter (#125) * added tokenize parameter Added tokenize parameter to restAPI documentation in Objects and in release Notes corrected tokenize parameter type in windows SDK * add tokenize parameter REST API: added tokenize parameter to both transaction object and to release notes Windows SDK: corrected the tokenize parameter type from String to Boolean --- restapi_versioned_docs/version-REST API 2.20.0/restobjects.md | 1 + .../version-REST API 2.20.0/restreleasenotes.md | 3 ++- .../version-Windows SDK 4.3.1/windowsobjects.md | 2 +- .../version-Windows SDK 4.3.1/windowsreleasenotes.md | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md index 285a772..c31f099 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md @@ -569,6 +569,7 @@ An object to store information about the request sent to the payment terminal. | `metadata`
    [*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `transactionReference`
    *String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| | `MoneyRemittanceOptions`
    [*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
    *Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| **Code example** diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md index 62ff25c..83cf468 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -14,8 +14,9 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting -Added "commands" +Added "commands" to allow greater device control options +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 2.17.0 **Features:** diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md index d3bb09d..f4e3ed2 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md @@ -351,7 +351,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
    *String* | **Budget is only available for sale transactions**.
    A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
    *String*|**String CustomerReference is available for all transactions.**
    A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`tokenize`
    *String*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +|`tokenize`
    *Boolean*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| |`DuplicateCheck`
    *String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



    ** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


    The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| | `Metadata1`
    *String*|**String Metadata1 is available for all transactions.**
    A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata2`
    *String*|**String Metadata2 is available for all transactions.**
    A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
    Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md index fcc830e..8352047 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md @@ -11,7 +11,7 @@ Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6. ## 4.3.1 **Features:** -A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md#3). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. +A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 4.2.0 **Features:** From 0d0d3b7b493fc2d22891b8e66af65758e530b012 Mon Sep 17 00:00:00 2001 From: Carlos Date: Fri, 23 May 2025 11:55:44 +0200 Subject: [PATCH 097/115] SDK-3856 iOS SDK 4.0.2 (#129) * feat: included version 4.0.2 * chore: removed unused section * feat: included release notes section for SDK iOS --- ios/iosdevicemanagement.md | 2 +- ios/iosevents.md | 2 +- ios/iosinstallation.md | 2 +- ios/iosintegration.md | 2 +- ios/iosmigration.md | 2 +- ios/iosobjects.md | 2 +- ios/iosprocessing.md | 2 +- ios/iosreleasenotes.md | 25 + ios/iossdkprocessing.md | 2 +- ios/iostransactions.md | 2 +- .../iosdevicemanagement.md | 2 +- .../version-iOS SDK 4.0.0/iosevents.md | 2 +- .../version-iOS SDK 4.0.0/iosobjects.md | 2 +- .../version-iOS SDK 4.0.0/iosreleasenotes.md | 17 + .../version-iOS SDK 4.0.0/iossdkprocessing.md | 2 +- .../version-iOS SDK 4.0.0/iostransactions.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.1/ios | 2599 ----------------- .../iosdevicemanagement.md | 2 +- .../version-iOS SDK 4.0.1/iosevents.md | 2 +- .../version-iOS SDK 4.0.1/iosinstallation.md | 2 +- .../version-iOS SDK 4.0.1/iosintegration.md | 2 +- .../version-iOS SDK 4.0.1/iosmigration.md | 2 +- .../version-iOS SDK 4.0.1/iosobjects.md | 2 +- .../version-iOS SDK 4.0.1/iosprocessing.md | 2 +- .../version-iOS SDK 4.0.1/iosreleasenotes.md | 21 + .../version-iOS SDK 4.0.1/iossdkprocessing.md | 2 +- .../version-iOS SDK 4.0.1/iostransactions.md | 2 +- .../iosdevicemanagement.md | 313 ++ .../version-iOS SDK 4.0.2/iosevents.md | 333 +++ .../version-iOS SDK 4.0.2/iosinstallation.md | 98 + .../version-iOS SDK 4.0.2/iosintegration.md | 188 ++ .../version-iOS SDK 4.0.2/iosintroduction.md | 39 + .../version-iOS SDK 4.0.2/iosmigration.md | 89 + .../version-iOS SDK 4.0.2/iosobjects.md | 762 +++++ .../version-iOS SDK 4.0.2/iosprocessing.md | 23 + .../version-iOS SDK 4.0.2/iosreleasenotes.md | 25 + .../version-iOS SDK 4.0.2/iossdkprocessing.md | 373 +++ .../version-iOS SDK 4.0.2/iostransactions.md | 582 ++++ .../version-iOS SDK 4.0.2-sidebars.json | 8 + ios_versions.json | 1 + 40 files changed, 2920 insertions(+), 2622 deletions(-) create mode 100644 ios/iosreleasenotes.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md delete mode 100644 ios_versioned_docs/version-iOS SDK 4.0.1/ios create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosdevicemanagement.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosevents.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosinstallation.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosintegration.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosintroduction.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosmigration.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosobjects.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosprocessing.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iossdkprocessing.md create mode 100644 ios_versioned_docs/version-iOS SDK 4.0.2/iostransactions.md create mode 100644 ios_versioned_sidebars/version-iOS SDK 4.0.2-sidebars.json diff --git a/ios/iosdevicemanagement.md b/ios/iosdevicemanagement.md index 98f35b7..2b3b8eb 100644 --- a/ios/iosdevicemanagement.md +++ b/ios/iosdevicemanagement.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 id: iosdevicemanagement --- diff --git a/ios/iosevents.md b/ios/iosevents.md index 3cadb49..a50716c 100644 --- a/ios/iosevents.md +++ b/ios/iosevents.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 10 id: iosevents --- diff --git a/ios/iosinstallation.md b/ios/iosinstallation.md index 4310562..9c7560b 100644 --- a/ios/iosinstallation.md +++ b/ios/iosinstallation.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 id: iosinstallation --- diff --git a/ios/iosintegration.md b/ios/iosintegration.md index 47b46cc..b42abaf 100644 --- a/ios/iosintegration.md +++ b/ios/iosintegration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 id: iosintegration --- diff --git a/ios/iosmigration.md b/ios/iosmigration.md index e4f5879..d99260b 100644 --- a/ios/iosmigration.md +++ b/ios/iosmigration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 id: iosmigration --- diff --git a/ios/iosobjects.md b/ios/iosobjects.md index 1233393..ce8d0a0 100644 --- a/ios/iosobjects.md +++ b/ios/iosobjects.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 id: iosobjects --- diff --git a/ios/iosprocessing.md b/ios/iosprocessing.md index 6d32c3e..ea2885b 100644 --- a/ios/iosprocessing.md +++ b/ios/iosprocessing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 id: iosprocessing --- diff --git a/ios/iosreleasenotes.md b/ios/iosreleasenotes.md new file mode 100644 index 0000000..3368714 --- /dev/null +++ b/ios/iosreleasenotes.md @@ -0,0 +1,25 @@ +--- +sidebar_position: 2 +id: iosreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.2 +**Fixes**: +- Crash due to vector index out of bounds. + +## 4.0.1 +**Fixes**: + - Multi MID fix for INTERAC and POSTBRIDGE acquirers. + +## 4.0.0 +**Features**: + - Support for Multi MID and HiPro scanner fixes. + diff --git a/ios/iossdkprocessing.md b/ios/iossdkprocessing.md index f754bb5..b614ac1 100644 --- a/ios/iossdkprocessing.md +++ b/ios/iossdkprocessing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 id: iossdkprocessing --- diff --git a/ios/iostransactions.md b/ios/iostransactions.md index 80d2df2..a0fd2bb 100644 --- a/ios/iostransactions.md +++ b/ios/iostransactions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 id: iostransactions --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosdevicemanagement.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosdevicemanagement.md index dfc5cc4..ee280f9 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iosdevicemanagement.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosdevicemanagement.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 id: iosdevicemanagement --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosevents.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosevents.md index a9150bb..227794a 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iosevents.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosevents.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 10 id: iosevents --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosobjects.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosobjects.md index 5aceabd..6fa2116 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iosobjects.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosobjects.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 id: iosobjects --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md new file mode 100644 index 0000000..e3dff0c --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md @@ -0,0 +1,17 @@ +--- +sidebar_position: 2 +id: iosreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.0 +**Features**: + - Support for Multi MID and HiPro scanner fixes. + diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iossdkprocessing.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iossdkprocessing.md index 2a581c3..b3ebfc1 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iossdkprocessing.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iossdkprocessing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 id: iossdkprocessing --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iostransactions.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iostransactions.md index c24f048..400bfe4 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iostransactions.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iostransactions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 id: iostransactions --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/ios b/ios_versioned_docs/version-iOS SDK 4.0.1/ios deleted file mode 100644 index 376d7be..0000000 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/ios +++ /dev/null @@ -1,2599 +0,0 @@ - - -# iOS SDK 4.0.1 - - -## Introduction - - - - -The Handpoint iOS SDK provides a simple application programming interface for the Handpoint card readers. - -:::tip - -Please note that before submitting an app to the Apple App store a MFi hardware request has to be submitted to Apple, -to be able to use an external accessory. Please fill our this form before submitting your app to the App store and we will get back to you. -If you have any questions, contact us for more details. - -::: - -## Installation - - -### CocoaPods - -CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command: - -```` -$ gem install cocoapods -```` - -If you don't have a Podfile yet: - -```` -$ pod init -```` - -To integrate HandpointSDK into your Xcode project using CocoaPods, specify it in your `Podfile`: - -```` -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' -use_frameworks! - -target 'your_target' do - pod 'HandpointSDK', '~> 3.2.3' -end -```` - -Then, run the following command: - -```` -$ pod install -```` - -### Carthage - -[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. - -You can install Carthage with [Homebrew](https://brew.sh/) using the following command: - -``` -$ brew update -$ brew install carthage -``` - -To integrate HandpointSDK into your Xcode project using Carthage, specify it in your `Cartfile`: - -```` -github "handpoint/HandpointSDK-iOS" -````` - -Run `carthage update` to build the framework and drag the built `HandpointSDK.framework` into your Xcode project. - -### Manually - -If you'd rather handle the dependency manually there are three approaches to include ```HandpointSDK``` in your project: - -#### Prebuilt static library - -Download the latest pre-built static library from [Handpoint's developer portal](https://www.handpoint.com/docs/device/iOS/) and refer to the documentation there for the installation steps. - -#### Building the project yourself - -Download the latest version from the master branch: - -``` -$ git clone https://github.com/handpoint/HandpointSDK-iOS.git -``` - -Alternatively you can add it as a git [submodule](https://git-scm.com/docs/git-submodule): - -``` -$ git submodule add https://github.com/handpoint/HandpointSDK-iOS.git -``` - -### Framework - -You'll find the dynamic framework project called `HandpointSDK.xcodeproj` at the root of the repo. - -Static Library -You'll find the static library project called `headstart.xcodeproj` under the `Library` folder. - -We **strongly** discourage you from building this project yourself. - -This project contains several targets, you need to build the aggregated target `device-simulator Release` - -This target produces a .zip file in the same directory as the `headstart.xcodeproj` file containing both the library and the simulator library. - -## Migration from 3.X - - -:::tip -Version 4.0.0 introduces a well defined, typed, way of passing extra values, options, parameters or flags to the financial transactions. -::: - - -We have unified all the extra and optional parameters in an Options object. Different operations have different options. - -**1. For a [Sale](#2) or [Sale and Tokenize operation](#4) please see SaleOptions**
    If you use a customer reference: - -``` - SaleOptions *options = [SaleOptions new]; - options.customerReference = @"Your customer reference"; -``` - - -If you need Multi MID / Custom merchant Authentication: - - -````objectivec - MerchantAuth *auth = [MerchantAuth new]; - Credential *cred = [Credential new]; - //Optionally - cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; - //Optionally - cred.mid = @"mid"; - //Optionally - cred.tid = @"tid"; - //Add as many credentials as Acquirers your merchant have agreements with - [auth add:cred]; - options.merchantAuth = auth; -``` - -If you want to specify the budget period `Only available for SureSwipe`: - -````objectivec -options.divideByMonths = @"YOUR_BUDGET_NUMBER"; - ```` - -Finally: - -````objectivec -[self.api saleWithAmount:amount currency:currency options:options]; -```` - - -**2. Similar to SaleOptions, but with less possible parameters, for a [Refund](#5) operation, please see RefundOptions**
    If you use a customer reference: - -````objectivec - SaleOptions *options = [SaleOptions new]; - options.customerReference = @"Your customer reference"; -```` - -If you need Multi MID / Custom merchant Authentication: - -````objectivec -MerchantAuth *auth = [MerchantAuth new]; - Credential *cred = [Credential new]; - //Optionally - cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; - //Optionally - cred.mid = @"mid"; - //Optionally - cred.tid = @"tid"; - //Add as many credentials as Acquirers your merchant have agreements with - [auth add:cred]; - options.merchantAuth = auth; -```` -Finally: - -```objectivec -[self.api refundWithAmount:amount currency:currency transaction:originalTransactionID options:options]; -``` - -**3. For the rest of operations, please see Options**
    If you use a customer reference: - -```objectivec -options.customerReference = @"Your customer reference"; -``` - -## Integration Guide - -### Files in iOS SDK - -#### If you're using the library/Cocoapods: - -- **HandpointAll.h**: #import this header file into your classes. -- **libheft.a**: The SDK library. - -#### If you're using the framework/Carthage: - -- ** HandpointSDK.h**: #import this header file into your classes. -- **HandpointSDK.framework**: The SDK library. - -The SDK also includes a simulator, a library configured to simulate a card reader - intended for early development of an user interface. To use it, just link the libheft.a file in the HeftSimulatorLibrary folder, instead of the actual SDK library. - -### Development settings for the SDK - -- **Dependencies**:The Heft library depends on the``` ExternalAccessory``` and ``` libc++.dylib``` frameworks included with the iOS SDK. These frameworks and the **libheft.a** SDK library itself need to be linked to your project for the Handpoint interface to work properly. - -- **Communication protocol**: Your application needs to support the card reader communication protocol. For this reason, the ```com.datecs.pinpad``` string needs to be added to the ```Supported external accessory protocols``` in the **.plist file**: - -````xml - UISupportedExternalAccessoryProtocols - - com.datecs.pinpad - -```` - -- **Background mode support**: Your application needs to support connection to external devices when in the background. For this reason, in the "Capabilities" section of the project settings, the **Background Modes** profile needs to be ON, and the ```External accessory communication ``` option must be checked. This is equivalent to adding the following entry in the .plist file: - - -````xml - UIBackgroundModes - - external-accessory - -```` - -- **C++ linker flag**: A part of the library is written in c++ therefore the **-lc++ linker flag** needs to be set. Add it under "Other Linker Flags" under the "Linking" section of your projects settings "Build Settings" tab. -- **Other settings**: To prevent the warning: "file was built for archive which is not the architecture being linked (armv7s)", **set Build Active Architecture Only** to YES. - - -### Usage summary - -Any application using the Handpoint SDK should follow these steps: - -1. Define a class that implements the** HeftDiscoveryDelegate **protocol. -This class defines the behavior of the app when discovery related events are received from the SDK. -2. Define a class that implements the **HeftStatusReportDelegate** protocol (it can be the same as above). -This class defines the behavior of the app when connection and transaction related events are received from the SDK -3. Get a reference to the HeftManager singleton and assign your HeftDiscoveryDelegate instance as delegate. -4. If device is available through BT connection, start the discovery process by calling the** startDiscovery** function of the HeftManager and recover a list of the discovered devices by calling the **connectedCardReaders **function of the HeftManager. -5. If device is using a Lightning connector (HiPro devices), recover the device by directly calling the **connectedCardReaders** function of the HeftManager. -6. Connect to a device by calling the **clientForDevice** function of the HeftManager. -7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. -8. From this point, make transactions and have fun! - -### Usage details - -1. Define a class that implements the ** HeftDiscoveryDelegate **protocol. -This class will define the behavior of the application when discovery related events are received from the SDK. - -````objectivec - @interface MyDiscoveryDelegate () - @implementation MyDiscoveryDelegate -```` - -2. Define a class that implements the** HeftStatusReportDelegate **protocol (it can be the same as above). -This class will define the behavior of the application when connection and transaction related events are received from the SDK. - -````objectivec - @interface MyStatusReportDelegate () - @implementation MyStatusReportDelegate -```` - -3. Get a reference to the HeftManager singleton in SDK by calling the **sharedManager** class method. -Assign your HeftDiscoveryDelegate instance as delegate of the manager. - -````objectivec - MyDiscoveryDelegate* myDiscoveryDelegate = [[alloc MyDiscoveryDelegate] init]; - HeftManager* manager = [HeftManager sharedManager]; - manager.delegate = myDiscoveryDelegate; -```` - -4. If device is available through BT connection, start the discovery process by calling the **startDiscovery** function of the HeftManager. - -````objectivec - [manager startDiscovery]; -```` - -When a device is selected by the user in the “Select device” popup window, the **didFindAccessoryDevice** function of the HeftDiscoveryDelegate is invoked. - -````objectivec - - (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice - { - NSLog(@"Found new device"); - //Connect to found device or store it for later - } -```` - -When the discovery process is finished, the **didDiscoverFinished** function of the HeftDiscoveryDelegate instance will be invoked. Recover a list of all the discovered devices by calling the **connectedCardReaders** function of the HeftManager. - -````objectivec - - (void)didDiscoverFinished - { - NSMutableDictionary *discoveredDevices = [self.manager connectedCardReaders]; - } -```` - -5. If device is using a Lightning connection (HiPro devices), skip the previous step and recover the device by directly calling the **connectedCardReaders** function of the HeftManager. - -````objectivec -HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstObject]; -```` - -6. Connect to a device by calling the **clientForDevice** function of the HeftManager. - -Expected parameters of this function are: - - -* A discovered device (HeftRemoteDevice object). - -* A shared secret. The shared secret is a unique identifier. It is a used to link a merchant with his readers. Each one of your merchants will be assigned a different shared secret so it needs to be a configurable value in your application or backend. If you received a development kit with a card reader, our support team probably sent you a shared secret via email already. - -* A HeftStatusReportDelegate instance, which will be notified of all the events related with the device. - -```` objectivec - // Declare the shared secret (below SS is an example, please put the one sent by our support team) - NSString *sharedSecret =@"0102030405060708091011121314151617181920212223242526272829303132"; - // Connect to reader - [manager clientForDevice:device - sharedSecret:mySharedSecret - delegate:myStatusReportDelegate]; -```` - -7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. Function receives as parameter a HeftClient object, whose reference must be stored since it is the communication bridge to the device we have connected to. - -```` objectivec - - (void)didConnect:(id )client - { - self.heftClient = client; - } -```` - -8. Once connected to the card reader, transactions can be started through the HeftClient object. For example, the next code starts a sale of 100 GBP: - -````objectivec -[self.heftClient saleWithAmount:100 currency:@"GBP" cardholder:YES]; -```` - -9. When a transaction has been initiated (f.ex saleWithAmount), the HeftClient alerts the HeftStatusReportDelegate object by invoking **responseStatus** during the process and **responceFinanceStatus** when the process has finished. - -````objectivec - - (void)responseStatus:(id)info - { - NSLog(@"responseStatus:"); - NSLog(info.status); - NSLog(info.xml.description); - } - - - (void)responseFinanceStatus:(id)info - { - NSLog(@"responseFinanceStatus:"); - NSLog(info.status); - NSLog(info.customerReceipt); - NSLog(info.xml.description); - } -```` - -10. In case you are using the **SDK simulator**, the behavior changes according to the amount of the transaction: - -| **Amount** | **Behavior** | -| ----------- | ----------- | -| 1000 | Declined transaction| -| 2000 | User Cancelled| -| 3000 | Signature Requested| -| Other amount | Approved transaction| - -## Processing Payments Simulation - -Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our server: - -**Sale amounts** - -| Amount | Behaviour | -| ----------- | ----------- | -| 37.79 | Issuer response code = 01 (Refer to issuer) | -| 37.84 | Issuer response code = 05 (Not authorized) | -| 37.93 | Issuer response code = 04 (Pick up card) | -| 37.57 | Request is partially approved | -| 37.68 | Request timeout | - -## SDK integration example - -### HandpointModule header - -**HandpointModule.h** - -````objectivec -#import "HandpointAll.h" - -@interface HandpointModule : NSObject - -- (instancetype)initWithSharedSecret:(NSString *)sharedSecret; - -- (void)saleWithAmount:(NSInteger)amount - currency:(NSString *)currency; - -- (void)refundWithAmount:(NSInteger)amount - currency:(NSString *)currency; - -- (void)saleReversalWithAmount:(NSInteger)amount - currency:(NSString *)currency - originalTransactionID:(NSString *)originalTransactionID; - -- (void)refundReversalWithAmount:(NSInteger)amount - currency:(NSString *)currency - originalTransactionID:(NSString *)originalTransactionID; - -- (void)connectToAddress:(NSString *)address; - -- (void)setLogLevel:(eLogLevel)logLevel; - -- (void)getDeviceLogs; - -- (void)getPendingTransaction; - -- (void)update; - -- (void)listDevices; - -@end -```` - -### HandpointModule - -**HandpointModule.m** - -````objectivec -#import "" -#import "HandpointModule.h" -#import "HeftRemoteDevice+SendableDevice.h" -#import "SDKEvent.h" -#import "ConnectionStatus.h" -#import "Currency.h" -#import "CDVInvokedUrlCommand+Arguments.h" -#import "StatusInfo.h" -#import "TransactionResult.h" - -typedef NS_ENUM(NSInteger, ConnectionStatus) -{ - ConnectionStatusNotConfigured, - ConnectionStatusConnected, - ConnectionStatusConnecting, - ConnectionStatusDisconnected, - ConnectionStatusDisconnecting, - ConnectionStatusInitializing -}; - -@interface HandpointModule () - -@property (nonatomic) HeftManager* manager; -@property (nonatomic, strong) id api; -@property (nonatomic) NSString *ssk; -@property (nonatomic) HeftRemoteDevice* preferredDevice; -@property (nonatomic) NSString *eventHandlerCallbackId; -@property (nonatomic) NSMutableDictionary *devices; - -@end - -@implementation HandpointModule - -- (instancetype)initWithSharedSecret:(NSString *)sharedSecret -{ - NSLog(@"\n\tpluginInitialize"); - self.manager = [HeftManager sharedManager]; - self.manager.delegate = self; - self.devices = [@{} mutableCopy]; - - [self fillDevicesFromConnectedCardReaders]; - - self.ssk = sharedSecret; -} - -- (void)saleWithAmount:(NSInteger)amount - currency:(NSString *)currency -{ - BOOL result = [self.api saleWithAmount:amount - currency:currency - cardholder:YES]; - - if (result == false) - { - //Do something - } -} - -- (void)refundWithAmount:(NSInteger)amount - currency:(NSString *)currency -{ - BOOL result = [self.api refundWithAmount:amount - currency:currency - cardholder:YES] - - if (result == false) - { - //Do something - } -} - -- (void)saleReversalWithAmount:(NSInteger)amount - currency:(NSString *)currency - originalTransactionID:(NSString *)originalTransactionID -{ - BOOL result = [self.api saleVoidWithAmount:amount - currency:currency - cardholder:YES - transaction:originalTransactionID]; - - if (result == false) - { - //Do something - } -} - -- (void)refundReversalWithAmount:(NSInteger)amount - currency:(NSString *)currency - originalTransactionID:(NSString *)originalTransactionID -{ - BOOL result = [self.api refundVoidWithAmount:amount - currency:currency - cardholder:YES - transaction:originalTransactionID]; - - if (result == false) - { - //Do something - } -} - -#pragma mark - Device Management - -- (void)connectToAddress:(NSString *)address -{ - HeftRemoteDevice *remoteDevice = self.devices[address]; - - if (remoteDevice) - { - BOOL isRemoteDeviceSameAsPreferred = self.preferredDevice && - [self.preferredDevice.address isEqualToString:remoteDevice.address]; - - // If we are already connected to this device, update shared secret - if (self.api && isRemoteDeviceSameAsPreferred) - { - // Already connected to device - } - else - { - self.preferredDevice = remoteDevice; - - [self.manager clientForDevice:remoteDevice - sharedSecret:self.ssk - delegate:self]; - } - - [self connectionStatusChanged:ConnectionStatusConnecting]; - } - else - { - NSLog(@"Can't connect. No device available. Have you searched?"); - } -} - -- (void)setLogLevel:(eLogLevel)logLevel -{ - [self.api logSetLevel:logLevel]; -} - -- (void)getDeviceLogs -{ - [self.api logGetInfo]; -} - -- (void)getPendingTransaction -{ - BOOL success = NO; - - if ([self.api isTransactionResultPending]) - { - success = [self.api retrievePendingTransaction]; - } - - if (success) - { - //... - } - else - { - //... - } -} - -- (void)update -{ - [self.api financeInit]; -} - -- (void)listDevices -{ - NSArray* devices = [self.manager connectedCardReaders]; - - /** - * A device can have four levels of connection: unpaired, paired, - * connected and connected in the SDK. - * - * Due to the nature of the iOS ExternalAccessory framework, - * devices that are already connected at an iOS level will not appear in a normal search, - * as they already appear through the "connectedCardReaders" array in the manager - * (Yeah, I know) - * - * So the "if" takes care of differentiating those two cases - * - * If we have device(s) connected we just go for those, otherwise, search. - */ - - if(devices.count) - { - //We have device(s) already connected, we skip the search. - for (HeftRemoteDevice *device in devices) - { - [self addDevice:device]; - } - - [self didDiscoverFinished]; - } - else - { - //We search and wait... - [self.manager startDiscovery]; - } -} - -# pragma mark - Callbacks - -- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice -{ - [self addDevice:newDevice]; -} - -- (void)didLostAccessoryDevice:(HeftRemoteDevice *)oldDevice -{ - [self removeDevice:oldDevice]; - - if(self.preferredDevice && self.preferredDevice.address == oldDevice.address) - { - [self connectionStatusChanged:ConnectionStatusDisconnected]; - - self.preferredDevice = nil; - } -} - -- (void)didDiscoverFinished -{ - [self fillDevicesFromConnectedCardReaders]; - - for (NSString *key in [self.devices allKeys]) - { - HeftRemoteDevice *device = self.devices[key]; - - if ([device.address isEqualToString:]) - { - //Do something with the device if it's the same one you expect. - break; - } - } -} - -- (void)didConnect:(id )client -{ - if(client) - { - self.api = client; - - [self connectionStatusChanged:ConnectionStatusConnected]; - } -} - -- (void)connectionStatusChanged:(ConnectionStatus)status -{ - //Here you get notified of connection status changes -} - -- (NSString *)stringFromConnectionStatus:(ConnectionStatus)status -{ - switch(status) - { - case ConnectionStatusNotConfigured: - return @"NotConfigured"; - case ConnectionStatusConnected: - return @"Connected"; - case ConnectionStatusConnecting: - return @"Connecting"; - case ConnectionStatusDisconnected: - return @"Disconnected"; - case ConnectionStatusDisconnecting: - return @"Diconnecting"; - case ConnectionStatusInitializing: - return @"Initializing"; - } -} - -- (void)responseStatus:(id )info -{ - //Here you'll get status updates during the transaction -} - -- (void)responseError:(id )info -{ - //Here if something went wrong -} - -- (void)responseFinanceStatus:(id )info -{ - //Here's the result of your transaction -} - -- (void)responseLogInfo:(id )info -{ - NSLog(@"\n\tresponseLogInfo: %@", info.status); -} - -- (void)requestSignature:(NSString *)receipt -{ - [self.api acceptSignature:YES]; -} - -- (void)addDevice:(HeftRemoteDevice *)device -{ - self.devices[device.address] = device; -} - -- (void)removeDevice:(HeftRemoteDevice *)device -{ - if (self.devices[device.address]) - { - [self.devices removeObjectForKey:device.address]; - } -} - -- (void)fillDevicesFromConnectedCardReaders -{ - for (HeftRemoteDevice *device in [self.manager connectedCardReaders]) - { - [self addDevice:device]; - } -} - -@end -```` - -## Transactions - -### Sale{#2} - -`saleWithAmount` - -A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount *`
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `currency *`
    *NSString* | 3 letter currency code in accordance to ISO4217| -| `options`
    *SaleOptions* | An object to store all the customization options for a sale.| - -**Code example** - -````objectivec -//If you just need a plain vanilla sale: -[api saleWithAmount:100 - currency:Currency.EUR.alpha]; - -//But you can customize your sale: -SaleOptions *options = [SaleOptions new]; -//Optionally -options.customerReference = @"Your customer reference"; -//If you need Multi MID / Custom merchant Authentication: -MerchantAuth *auth = [MerchantAuth new]; -Credential *cred = [Credential new]; -//Optionally -cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; -//Optionally -cred.mid = @"mid"; -//Optionally -cred.tid = @"tid"; -//Add as many credentials as Acquirers your merchant have agreements with -[auth add:cred]; -options.merchantAuth = auth; -//If you want to specify the budget period -//Only available for SureSwipe -//Here it's 3 months -options.divideByMonths = @"3"; - -[api saleWithAmount:100 - currency:Currency.EUR.alpha - options:options]; -```` - -**Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader. - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**requestSignature**](#17) -*** -Invoked if card verification requires signature. - -[**responseFinanceStatus **](#16) -*** -Invoked when the card reader finishes processing the transaction - -** Returns** - -**Boolean** - -YES if operation starts successfully - -### Sale Reversal{#3} - -`saleVoidWithAmount` - -Request a void operation on previous sale transaction, referred to by the parameter transaction. Parameters amount, currency and present must be the same as the in the sale to be voided. This operation reverts (if possible) a specific sale identified with a transaction id. Note that transactions can only be reversed within the same day as the transaction was made. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount *`
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `currency *`
    *NSString* | 3 letter currency code in accordance to ISO4217 | -| `transaction *`
    *NSString* | TransactionID of the sale transaction to be voided | -| `options`
    *Options* | An object to store all the customization options for this operation.| - -**Code example** - -```objectivec -//If you just need a plain vanilla sale reversal: -[api saleReversalWithAmount:100 - currency:Currency.EUR.alpha - transactionId:originalTransactionID - options:options]; - -//But you can customize your sale: -Options *options = [Options new]; -//Optionally -options.customerReference = @"Your customer reference"; - -[api saleReversalWithAmount:100 - currency:Currency.EUR.alpha - transactionId:@"00000000-0000-0000-0000-000000000000" - options:options]; -``` - -**Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError **](#15) -*** -Invoked to inform when an error response happens. - -[**responseFinanceStatus**](#16) -*** -Invoked when the card reader finishes processing the transaction - -**Returns** - -**Boolean** -YES if operation starts successfully - - -### Sale And Tokenize Card{#4} - -`saleAndTokenizeCardWithAmount` - -A sale initiates a payment operation to the card reader. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount *`
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `currency *`
    *NSString* | 3 letter currency code in accordance to ISO4217| -| `options`
    *SaleOptions* | An object to store all the customization options for a sale.| - -**Code example** - -````objectivec -//If you just need a plain vanilla sale tokenization: -[api saleAndTokenizeWithAmount:100 - currency:Currency.EUR.alpha]; - -//But you can customize your sale: -SaleOptions *options = [SaleOptions new]; -//Optionally -options.customerReference = @"Your customer reference"; -//If you need Multi MID / Custom merchant Authentication: -MerchantAuth *auth = [MerchantAuth new]; -Credential *cred = [Credential new]; -//Optionally -cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; -//Optionally -cred.mid = @"mid"; -//Optionally -cred.tid = @"tid"; -//Add as many credentials as Acquirers your merchant have agreements with -[auth add:cred]; -options.merchantAuth = auth; -//If you want to specify the budget period -//Only available for SureSwipe -//Here it's 3 months -options.divideByMonths = @"3"; - -[api saleAndTokenizeWithAmount:100 - currency:Currency.EUR.alpha - options:options]; -```` - -**Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**requestSignature**](#17) -*** -Invoked if card verification requires signature. - -[**responseFinanceStatus**](#16) -*** -Invoked when the card reader finishes processing the transaction - -**Returns** - -**Boolean** - -YES if operation starts successfully - -### Refund{#5} - -`refundWithAmount` - -A refund initiates a refund operation to the card reader. This operation moves funds from your account to the cardholders credit card. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount *`
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `currency *`
    *NSString* | Currency of the charge| -| `transaction *`
    *NSString* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| -| `options`
    *MerchantAuthOptions* | An object to store all the customization options for a refund.| - -**Code example** - -````objectivec -//If you just need a plain vanilla refund: -[api refundWithAmount:100 - currency:Currency.EUR.alpha - transaction:@"00000000-0000-0000-0000-000000000000"]; - -//But you can customize your sale: -MerchantAuthOptions *options = [MerchantAuthOptions new]; -//Optionally -options.customerReference = @"Your customer reference"; -//If you need Multi MID / Custom merchant Authentication: -MerchantAuth *auth = [MerchantAuth new]; -Credential *cred = [Credential new]; -//Optionally -cred.acquirer = [Credential getAcquirerFromString:@"acquirer"]; -//Optionally -cred.mid = @"mid"; -//Optionally -cred.tid = @"tid"; -//Add as many credentials as Acquirers your merchant have agreements with -[auth add:cred]; -options.merchantAuth = auth; - -[api refundWithAmount:100 - currency:Currency.EUR.alpha - transaction:@"00000000-0000-0000-0000-000000000000" - options:options]; -```` - -** Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError**](#15) -*** -Invoked when the card reader finishes processing the transaction - -[**responseFinanceStatus**](#16) -*** -Invoked to inform when an error response happens. - -**Returns** - -**Boolean** - -YES if operation starts successfully - -### Refund reversal{#6} - -`refundVoidWithAmount` - -Request a void operation on previous refund transaction, referred to by the parameter transaction. Parameters amount, currency and present must be the same as the in the refund to be voided. This operation reverts (if possible) a specific refund identified with a transaction id. Note that transactions can only be reversed within the same day as the transaction was made. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `amount *`
    *NSInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `currency *`
    *NSString* | 3 letter currency code in accordance to ISO4217| -| `transaction *`
    *NSString* | TransactionID of the refund transaction to be voided| -| `options`
    *Options* | An object to store all the customization options for this operation.| - -**Code example** - -````objectivec -//If you just need a plain vanilla refund reversal: -[api refundReversalWithAmount:100 - currency:Currency.EUR.alpha - transactionId:originalTransactionID - options:options]; - -//But you can customize your sale: -Options *options = [Options new]; -//Optionally -options.customerReference = @"Your customer reference"; - -[api refundReversalWithAmount:100 - currency:Currency.EUR.alpha - transactionId:@"00000000-0000-0000-0000-000000000000" - options:options]; -```` - -** Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**responseFinanceStatus**](#16) -*** -Invoked when the card reader finishes processing the transaction - -**Returns** - -**Boolean** - -YES if the operation was successfully sent to device - -### Accept signature{#7} - -`acceptSignature` - -A [*requestSignature*](#17) event is invoked during transaction when signature verification is needed (f.ex when payment is done with a magstripe card). The merchant is required to ask the cardholder for signature and approve (or disapprove) the signature. signatureRequired tells the card reader if the signature was approved by passing YES. To disapprove then NO is passed. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `flag *`
    *Boolean* | YES if signature is valid, NO otherwise| - - -**Code example** - -````objectivec -//acceptSignature: -//Inform the card reader if signature is valid or not --(IBAction)accept -{ - [heftClient acceptSignature:YES]; -} --(IBAction)decline -{ - [heftClient acceptSignature:NO]; -} -```` - -** Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**responseFinanceStatus**](#16) -*** -Invoked when the card reader finishes processing the transaction - - -### Retrieve Pending Transaction{#8} - -`retrievePendingTransaction` - -Retrieving a pending transaction fetches a transaction result that was lost due to unexpected disconnect between card reader and application. - -**Code example** - -````objectivec -//retrievePendingTransaction: -//Called when a pending transaction is discovered upon connecting to a specific card reader -- (void)didConnect:(id)client{ - heftClient = client; - - if(heftClient){ - if([heftClient isTransactionResultPending] == YES) { - // a pending transaction has been detected ... - // ... so, lets get it - [heftClient retrievePendingTransaction]; - } - } -} -```` - -** Events invoked** - -[**responseStatus**](#14) -*** -Invoked during the operation with different statuses from the card reader. - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**responseRecoveredTransactionStatus**](#18) -*** -Invoked when the card reader has returned a recovered transaction. - -**Returns** - -**Boolean** - -YES if operation starts successfully - -### Tip Adjustment{#9} - -`tipAdjustment` - -A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled automatically by the processor at the end of the day. -Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. -The tip adjustment method does not rely on a card reader and is therefore a separate method that must be initialized with a shared secret. The function is defined in the file HapiRemoteService.h - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `tipAmount *`
    *NSInteger* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| -| `transaction*`
    *NSString* | TransactionID (GUID) of the original sale transaction to be adjusted| - - -**Code example** - -````objectivec -//First, you need to include the following dependency -#include "HapiRemoteService.h" - -//Second, the shared secret needs to be initialized -NSString* shared_secret = @"0102030405060708091011121314151617181920212223242526272829303132"; -BOOL result = setupHandpointApiConnection(shared_secret); - -//Third, you need to retrieve the unique transaction id of the original sale transaction you want to adjust. The below GUID is only an example and will result in a decline from the host if used for tip adjustment -NSString* transaction = @"d50af540-a1b0-11e6-85e6-07b2a5f091ec"; - -//Fourth, let's tip adjust a transaction for $10.00! --(IBAction)tipAdjustment:(UIButton*) sender -{ - BOOL result = tipAdjustment(transaction, 1000, ^(TipAdjustmentStatus status) - { - if(status == TipAdjustmentAuthorised) { - - //Successfully adjusted! - - } - - else if(status == TipAdjustmentDeclined) { - - //Declined! - - } - - else if(status == TipAdjustmentFailed) { - - //Timeout! - - } - }); -} -```` - -**Returns** - -**status** - -- **TipAdjustmentAuthorised** (tip adjustment approved by the processor) -- **TipAdjustmentFailed** (system error or timeout) -- **TipAdjustmentDeclined** (tip adjustment declined by the processor) - -If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. - -### Tokenize Card{#10} - -`tokenizeCard` - -Initiates a card-tokenization operation to the card reader (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice). - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `reference *`
    *NSString* | string for customer reference| - - -**Code example** - -````objectivec -//Initiates a card tokenization operation. -[heftClient tokenizeCard]; -```` - - -** Events invoked** - -[**responseStatus**](#14) -*** -Invoked while during transaction with different statuses from card reader - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**requestSignature**](#17) -*** -Invoked if card verification requires signature. - -[**responseRecoveredTransactionStatus**](#18) -*** -Invoked when the card reader finishes processing the transaction - - -**Returns** - -**Boolean** - -YES if operation starts successfully - -## Device management - -### Shared Manager{#11} - -`sharedManager` - -Provides access to the heftManager. The heft manager is used for discovering devices and creating a HeftClient with a connection to selected device. - -**Code example** - -````objectivec -//SharedManager -//Provides access to the heftManager - -//Create an instance of the shared manager at set it's delegate -HeftManager* heftManager = [HeftManager sharedManager]; -heftManager.delegate = self; -```` - -**Returns** - -[**HeftManager**](#19) - -The heftManager instance - -### Client for device (NSString){#12} - -`clientForDevice` - -Creates a HeftClient object. If a connection is successful the HeftClient object is returned in the didConnect event. All transactions are done using the heftClient. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `device *`
    *NSInteger* | The device to connect to.| -| `sharedSecret *`
    *NSString* | Shared secret only known by the merchant and Handpoint.| -| `aDelegate *`
    *BOOL* | The HeftStatusReportDelegate for the HeftClient to report to.| - - -**Code example** - -````objectivec -//clientForDevice:sharedSecretString:delegate: -//Creates a HeftClient object(connection to device) -NSString* sharedSecret = @"0102030405060708091011121314151617181920212223242526272829303132"; --(void)connectToFirstCardReaderWith:(NSString*)sharedSecret; -{ - //Try to connect to first device in devices array - [heftManager clientForDevice:[[heftManager devicesCopy] objectAtIndex:0] sharedSecretString:sharedSecret delegate:self]; - //Client calls the didConnect delegate function if successful -} -```` - -**Events invoked** - -[**didConnect**](#20) -*** -Called when a connection to specified device was created. - -**Returns** - -**Boolean** - -YES if operation starts successfully - -### Start Discovery {#32} - -`startDiscovery` - -Displays a list of available accessory devices in a modal window. - -**Code example** - -````objectivec -//startDiscovery -//Starts the BT discovery process --(void)startDiscovery; -{ - [heftManager startDiscovery]; - //Start search activity indicator or other desired functions -} -```` - -### Set log level{#33} - -`logSetLevel` - -Sets the log level of the card reader. There are for levels of logging for the device: none, info, full, debug. Setting the log level means that relevant information concerning the application operation will be stored. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `level *`
    [eLogLevel](#13) | eLogLevel available types: eLogNone, eLogInfo, eLogFull, eLogDebug| - -**Code example** - -````objectivec -//logSetLevel: -//Sets the log level of the card reader. --(void)disableCardReaderLogs -{ - [heftClient logSetLevel:eLogNone]; -} --(void)enableCardReaderDebugLogs -{ - [heftClient logSetLevel:eLogDebug]; -} -```` - -**Returns** - -**Boolean** - -This method always returns YES - - -### Fetch logs{#34} - -`logSetLevel` - -Retrieves the logging info. Returns them in the responseLogInfo event. - -**Code example** - -````objectivec -//logGetInfo -//Retrieves the logging info. --(void)getLogsFromCardReader -{ - [heftClient logGetInfo]; -} -```` - -**Returns** - -**Boolean** - -This method always returns YES - -### Reset logs{#35} - -`logReset` - -Clears the logging information stored so far. - -**Code example** - -````objectivec -//logReset -//Clears the logging information stored so far --(void)clearLogs -{ - [heftClient logReset]; -} -```` - -**Returns** - -**Boolean** - -This method always returns YES - -### Enable scanner{#36} - -`enableScanner` - -Places the card reader in a scan mode. Only if the card reader supports it. To cancel/stop scan mode call the cancel method of the heft client. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `multiScan`
    *Boolean* | Yes [default] to activate multiScan mode - No to activate singleScan mode. Multi-scan mode allows the user to scan until scan operation is canceled or timeout occurs, single-scan mode is active until one scan has occurred then it disables the scan mode.| -| `buttonMode`
    *Boolean* | Yes [default] if buttonMode is on - No otherwise. If button mode is on then the operator needs to press the scan buttons to activate the scanner(during scan mode).| -| `timeoutSeconds`
    *NSInteger* | 0 [default] - card reader will determine when scanning should time out. x - the scanner will time out if x seconds of inactivity occur.| - -**Code example** - -````objectivec -//enableScanner:multiScan:buttonMode:timeoutSeconds -//Places the card reader in a scan only mode. -//To cancel/stop scan mode call cancel function. --(IBAction)startScan -{ - [heftClient enableScanner]; -} --(IBAction)startMultiScan -{ - [heftClient enableScannerWithMultiScan:YES]; -} -```` - -**Events invoked** - -**responseScannerEvent** -*** -Called to inform that a scan has been performed, several calls can be expected. Several calls to this method happen after a scan action has been performed to inform about scan information operation. The info object contains scanCode, status and a dictionary (xml). - -### Disable scanner - -`disableScanner` - -Disables the scanner if possible - -**Code example** - -````objectivec -//disableScanner -//Disable the scanner - -(IBAction)disableScanner -{ -[heftClient disableScanner]; -} -```` - -**Events invoked** -*** -[**responseScannerDisabled**](#42) - -Called to inform that a scan has been performed, several calls can be expected. Several calls to this method happen after a scan action has been performed to inform about scan information operation. The info object contains scanCode, status and a dictionary (xml). - -### financeInit{#47} - -`financeInit` - -The update operation checks for update to the card reader and initiates an update if needed. The update can either be a software update or a configuration update. - -**Code example** - -````objectivec -//financeInit -//Initializes the card reader and updates config. --(IBAction)updateCardReader -{ - [heftClient financeInit]; -} -```` - -**Events invoked** - -[**responseStatus**](#14) -*** -Called to inform that a scan has been performed, several calls can be expected. Several calls to this method happen after a scan action has been performed to inform about scan information operation. The info object contains scanCode, status and a dictionary (xml).**responseStatus**](#14) - -[**responseError**](#15) -*** -Invoked to inform when an error response happens. - -[**responseFinanceStatus**](#16) -*** -Invoked when the card reader finishes processing the transaction - -**Returns** - -**Boolean** - -This method always returns YES - -### Get SDK version - -`getSDKVersion` - -Returns the current SDK version number in string format - -**Code example** - -````objectivec -//getSDKVersion -//Log SDK version number - NSLOG(@"SDK version: %@", [heftManager getSDKVersion]; -```` - -### Get SDK build number - -`getSDKBuildNumber` - -Returns the current SDK build number in string format - -**Code example** - -````objectivec -//getSDKBuildNumber -//Log SDK build number - NSLOG(@"SDK build: %@", [heftManager getSDKBuildNumber]; -```` - -## Events - -### didConnect{#20} - -`didConnect` - -Called when a connection to the client has been established through the method clientForDevice. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `client *`
    [HeftClient](#22) | Yes [default] to activate multiScan mode - No to activate singleScan mode. Multi-scan mode allows the user to scan until scan operation is canceled or timeout occurs, single-scan mode is active until one scan has occurred then it disables the scan mode.| - -**Code example** - -````objectivec -//didConnect: -//Called when a connection to specified device was created. --(void)didConnect:(id)client -{ - // connected successfully to a device - // assign the client to our heftClient property - heftClient = client; -} -```` - -### didDiscoverFinished {#37} - -`didDiscoverFinished` - -When the modal window from startDiscovery is closed then this event is called. - -**Code example** - -````objectivec -//didDiscoverFinished -// This function gets called when discovery is finished -- (void)didDiscoverFinished; -{ - NSLog(@"Discover finished"); - //Stop search activity indicator or other desired functions -} -```` - - -### didFindAccessoryDevice{#38} - -`didFindAccessoryDevice` - -Notifies that new accessory device was found. When a card reader is detected this delegate is called. You can take the newDevice object and create a new heft client for that particular device or store it in memory to connect to it later. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `newDevice *`
    [HeftRemoteDevice](#23) | An object containing a reference to the accessory device| - -**Code example** - -````objectivec -//didFindAccessoryDevice -//Delegate that notifies that new accessory device was found. -- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice -{ - NSLog(@"Found new device"); - //Connect to device or store found device for later -} -```` - - -### didLostAccessoryDevice{#39} - - -`didLostAccessoryDevice` - -Notifies that accessory device was disconnected. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `oldDevice *`
    [HeftRemoteDevice](#23) | An object containing a reference to the accessory device| - -**Code example** - -````objectivec -//didLostAccessoryDevice -//Delegate that notifies that accessory device was disconnected -- (void)didLostAccessoryDevice:(HeftRemoteDevice*)oldDevice -{ - NSLog(@"Device disconnected"); - //Remove device from devices array - [heftManager.devicesCopy removeObject:oldDevice]; - //Do some cleanup after disconnecting if necessary - -} -```` - -### responseStatus{#14} - -`responseStatus` - -Called to inform about the status of the transaction, several calls can be expected. Several calls to this method happen after a transaction is initiated from the HeftClient to inform about status of operation. The info object contains a string (status) and a dictionary (xml). - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [ResponseInfo](#24) | Includes status code, status text and detailed xml.| - -**Code example** - -````objectivec -//responseStatus: -//Called to inform about the status of the transaction --(void)esponseStatus:(id)info -{ - NSLog(info.status); - NSLog(info.xml.description); -} -```` - -### responseFinanceStatus{#16} - -`responseFinanceStatus` - -Notifies that transaction has completed. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [FinanceResponseInfo](#25) | Information about current transaction status.| - -**Code example** - -````objectivec -//responseFinanceStatus: -//Called at the end of transaction to inform about the result of the operation --(void)responseFinanceStatus:(id)info -{ - NSLog(info.status); - NSLog(info.customerReceipt); - //print receipts -} -```` - -### responseError{#15} - -`responseError` - -Called to inform about the status of the transaction, several calls can be expected. Several calls to this method happen after a transaction is initiated from the HeftClient to inform about status of operation. The info object contains a string (status) and a dictionary (xml). - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [ResponseInfo](#24) | The info object contains a string (status) and a dictionary (xml).| - -**Code example** - -````objectivec -//responseError: -//Called when to inform when an error response happens. --(void)responseError:(id)info -{ - NSLog(info.status); - NSLog(info.xml.description); -} -```` - -### requestSignature{#17} - -`requestSignature` - -Is called if during a financial operation a signature from the customer is needed. The requestSignature delegate should be implemented to print out or display the receipt for the customer to sign and provide the merchant with the means to confirm the signature. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `receipt *`
    *NSString* | The receipt is a html formatted string containing a receipt for the customer to sign| - -**Code example** - -````objectivec -//requestSignature: -//Is called if a signature from the customer is needed. --(void)requestSignature:(NSString*)receipt -{ - NSLog(receipt); - //Display buttons to accept or decline customer signature - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"" message:@"sign?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; - [alert show]; -} -```` - -### cancelSignature{#40} - -`cancelSignature` - -Called if the signature request times out. If the card reader does not receive an approval for the signature within a certain timeframe (45 sec) it cancels the transaction and sends a notification to the app. - -**Code example** - -````objectivec -//cancelSignature -//Called if the signature request times out. --(void)cancelSignature -{ - NSLog(@"Signature request timed out"); -} -```` - -### responseScannerEvent{#41} - -`responseScannerEvent` - -Called to inform that a scan has been performed, several calls can be expected. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [ScannerEventResponseInfo](#26) | The info object contains scanCode, status and a dictionary (xml).| - -**Code example** - -````objectivec -//responseScannerEvent: -//Called to inform that a scan has been performed --(void)responseScannerEvent:(id)info -{ - NSLog(info.scanCode); //barcode scanned - NSLog(info.xml.description); -} -```` - -### responseScannerDisabled{#42} - -`responseScannerDisabled` - -Called to notify that the scanner has been disabled. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [ScannerDisabledResponseInfo](#27) | The info object contains information about the scanner operation.| - -**Code example** - -````objectivec -//responseScannerDisabled: -//Called to notify that the scanner has been disabled. --(void)responseScannerDisabled:(id)info -{ - NSLog(info.status); -} -```` - -### responseLogInfo{#43} - -`responseLogInfo` - -Called when logs have been downloaded from the card reader by using the logGetInfo method. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [LogInfo](#27) | The info object has the string property log which holds the log info in text with carriage returns.| - -**Code example** - -````objectivec -//responseLogInfo: -//Called when logs have been downloaded from the card reader by using the logGetInfo method. --(void)responseLogInfo:(id)info -{ - NSLog(info.log); - //write to log file -} -```` - -### responseRecoveredTransactionStatus{#44} - -`responseRecoveredTransactionStatus` - -This method is **OPTIONAL** and only required if retrievePendingTransaction will be called. - -**Parameters** - -| Parameter | Notes | -| ----------- | ----------- | -| `info *`
    [*ResponseInfo*](#24) | Information about the recovered transaction status.| -| |**If an attempt was made to recover a transaction when none was pending then this parameter WILL be nil.**| - -**Code example** - -````objectivec -//responseRecoveredTransactionStatus: -//Called when a pending transaction result has been recovered from the card reader -- (void)responseRecoveredTransactionStatus:(id)info{ - if(info != nil) { - if(info.statusCode == EFT_PP_STATUS_SUCCESS) { - NSLog(info.status); - NSLog(info.customerReceipt); - NSLog(info.merchantReceipt); - // print receipts and/or save receipts in transaction log - - if(info.financialResult == EFT_FINANC_STATUS_TRANS_APPROVED){ - // Process recovered authorized transaction result - } else if(info.financialResult == EFT_FINANC_STATUS_TRANS_DECLINED) { - // Process recovered declined transaction result - } - } else if(info.statusCode != EFT_PP_STATUS_NO_DATA_AVAILABLE) { - // some other error was detected while waiting for a pending transaction result - } - } - // else a pending transaction result was not found on the card reader -} -```` - -### Card Reader Requirements - -**Version Requirements** - -Card reader software v1.7.0+ and v2.1.7+ is required in order for this response to be received. - -## Objects - -### HeftManager{#19} - -`HeftManager` - -The HeftManager is used for discovering devices and to connect and create a HeftClient object for the appropriate device. The manager reports messages to HeftDiscoveryDelegate protocol during the discovery process. Starting the manager is usually the first thing that should be done after loading up an UIView that enables the user to search for and connect to BT devices. When starting the manager an object (usually the UIViewController itself) is passed as the HeftDiscoveryDelegate delegate to report to. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `devicesCopy`
    [NSArray] | **DEPRECATED_ATTRIBUTE**: Stored array which contains all found devices.| -| `connectedCardReaders`
    [NSArray] | Stored array which contains all found devices.| -| `delegate`
    [NSObjectHeftDiscoveryDelegate] | Key for value in mpedInfo| -| `version`
    *NSString* | Current HeftManager version.| - -**Code example** - -````objectivec -// Create a manager on view load -- (void)viewDidLoad{ - [super viewDidLoad]; - HeftManager* manager = [HeftManager sharedManager]; - manager.delegate = self; - [manager resetDevices]; // Clean out device list -} -```` - -**Methods** - -[**Start Discovery**](#29) -*** -- (void)startDiscovery; - -[**Shared Manager**](#30) -*** -+ (HeftManager*)sharedManager; - -[**Client for device (NSString)**](#31) -*** -- (void)clientForDevice:(HeftRemoteDevice *)device sharedSecret:(NSString *)sharedSecret delegate:(NSObject HeftStatusReportDelegate*)delegate; - -### HeftClient{#22} - -`HeftClient` - -High level interface for Headstart API. HeftClient handles the communication between the mPos app and the card reader. The HeftClient object also stores information about it's card reader device in the mpedInfo dictionary. Device Log operations are also implemented in HeftClient. To create a new HeftClient object the clientForDevice method is called from an instance of the HeftManager. Transaction and log requests (and the acceptSignature response) are done by calling HeftClient methods with the relevant input. The library reports the status of the requests by calling delegates of the HeftStatusReportDelegate protocol. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `sharedSecret`
    [NSString] | The shared secret is a key provided by Handpoint when you get your account that enables you to perform live operations with the card reader. However, if you're developing with a starter kit, the test shared secret is specified in the example.| -| `mpedInfo`
    [NSDictionary] | Dictionary with card reader info details, obtained by querying it from device on interface creation.| -| `isTransactionResultPending`
    [BOOL] | Indicates whether a transaction result is pending on the card reader.| -| | **Note: A pending transaction result is retained by the card reader if a disconnect occurs between card reader and app before the transaction result can be delivered during a SALE, REFUND or VOID processing.**| -| `kSerialNumberInfoKey`
    [NSString constant ] | Key for value in mpedInfo| -| `kPublicKeyVersionInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kEMVParamVersionInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kGeneralParamInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kManufacturerCodeInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kModelCodeInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kAppNameInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kAppVersionInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| -| `kXMLDetailsInfoKey`
    [NSString Constant ] | Key for value in mpedInfo| - - -**Code example** - -````objectivec -//clientForDevice:sharedSecret:delegate: -//Creates a HeftClient object(connection to device) --(void)connectToFirstCardReaderWith:(NSData*)sharedSecret; -{ - //Try to connect to first device in devices array - [heftManager clientForDevice:[[heftManager devicesCopy] objectAtIndex:0] sharedSecret:sharedSecret delegate:self]; - //Client calls the didConnect delegate function if successful -} - -//.... - -//didConnect: -//Called when a connection to specified device was created. --(void)didConnect:(id)client -{ - // connected successfully to a device - // assigne the client to our heftClient property - heftClient = client; -} - -// ..... - -// Do one sale later in code -[heftClient saleWithAmount:1000 currency:@"GBP" cardholder:YES]; -```` - -**Methods** - -[**cancel**](#32) -*** -- (void)cancel; - -[**saleWithAmount**](#2) -*** -- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present; - -[**saleWithAmount**](#2) -*** -- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference; - -[**saleWithAmount**](#2) -*** -- (BOOL)saleWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference; - -[**refundWithAmount**](#5) -*** -- (BOOL)refundWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present; - -[**refundWithAmount**](#5) -*** -- (BOOL)refundWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present reference:(NSString*)reference; - -[**saleVoidWithAmount**](#3) -*** -- (BOOL)saleVoidWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present transaction:(NSString*)transaction; - -[**refundVoidWithAmount**](#3) -*** -- (BOOL)refundVoidWithAmount:(NSInteger)amount currency:(NSString*)currency cardholder:(BOOL)present transaction:(NSString*)transaction; - -[**retrievePendingTransaction**](#8) -*** -- (BOOL)retrievePendingTransaction; - -[**enableScanner**](#36) -*** -- (BOOL)retrievePendingTransaction; - -[**enableScannerWithMultiScan**] -*** -- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan; - -[**enableScannerWithMultiScan**] -*** -- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan buttonMode:(BOOL)buttonMode; - -[**enableScannerWithMultiScan**] -*** -- (BOOL)enableScannerWithMultiScan:(BOOL)multiScan buttonMode:(BOOL)buttonMode timeoutSeconds:(NSInteger)timeoutSeconds; - -[**Disable scanner**](#37) -*** -- (BOOL)disableScanner; - -[**financeStartOfDay**] -*** -- (BOOL)financeStartOfDay; - -[**financeEndOfDay**] -*** -- (BOOL)financeEndOfDay; - -[**financeInit**](#47) -*** -- (BOOL)financeInit; - -[**logSetLevel**](#33) -*** -- (BOOL)logSetLevel:(eLogLevel)level; - -[**logReset**](#35) -*** -- (BOOL)logReset; - -[**logGetInfo**](#34) -*** -- (BOOL)logGetInfo; - -[**acceptSignature**](#7) -*** -- (void)acceptSignature:(BOOL)flag; - -[**getEMVConfiguration**](#7) -*** -- (BOOL)getEMVConfiguration; - - -### HeftRemoteDevice{#23} - -`HeftRemoteDevice` - -An object containing a reference to the accessory device which is passed to the HeftClient on creation. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `name`
    [NSString] | Name of device| -| `accessory`
    [EAAccessory] | The EAAccessory object| -| `address`
    [NSString] | Address of device| - - -### HeftDiscoveryDelegate - -`HeftDiscoveryDelegate` - -Notifications sent by the SDK on various events - new available device found, connection lost, connection found, etc - -**Methods** - -[**didDiscoverFinished**](#37) -*** -- (void)didDiscoverFinished; - -[**didFindAccessoryDevice**](#38) -*** -- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice; - -[**didLostAccessoryDevice**](#39) -*** -- (void)didLostAccessoryDevice:(HeftRemoteDevice*)oldDevice; - -### HeftStatusReportDelegate - -`HeftStatusReportDelegate` - -Notifications sent by the SDK on various events - connected to device, request signature, response on error etc. - -**Methods** - -[**didConnect**](#20) -*** -- (void)didConnect:(id-HeftClient)client; - -[**responseStatus**](#14) -*** -- (void)responseStatus:(id-ResponseInfo)info; - -[**responseError**](#15) -*** -- (void)responseError:(id-ResponseInfo)info; - -[**responseFinanceStatus**](#16) -*** -- (void)responseFinanceStatus:(id-FinanceResponseInfo)info; - -[**responseLogInfo**](#43) -*** -- (void)responseLogInfo:(id-LogInfo)info; - -[**requestSignature**](#17) -*** -- (void)requestSignature:(NSString*)receipt; - -[**cancelSignature**](#40) -*** -- (void)cancelSignature; - -[**responseRecoveredTransactionStatus**](#44) -*** -- (void)responseRecoveredTransactionStatus:(id-FinanceResponseInfo)info; - -[**responseScannerEvent**](#41) -*** -- (void)responseScannerEvent:(id-ScannerEventResponseInfo)info; - -[**responseScannerDisabled **](#2) -*** -- (void)responseScannerDisabled:(id-ScannerDisabledResponseInfo)info; - -[**responseEMVReport**](#43) -*** -- (void)responseEMVReport:(NSString *)report; - - -### ResponseInfo{#24} - -`ResponseInfo` - -A ResponseInfo object is passed to the ResponseStatus delegate. It contains information from the card reader about the status of the current transaction. There are two properties: status and xml. status is a string and xml is a dictionary. Usually status contains a message descriptive enough to know whats going on and is useful for displaying to user. The xml dictionary contains all elements of the XML formatted data passed from the card reader and has detailed information on the current state of the card reader. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `statusCode`
    *int* | A numerical representation of the status.| -| `status`
    [*Status as NSString*](#45) | Financial transaction status message.| -| `xml`
    [*XML as NSDictionary*](#46) | Feedback with xml details about transaction from the card reader.| - - -### FinanceResponseInfo{#25} - -`FinanceResponseInfo` - -A FinanceResponseInfo is passed to the responseFinanceStatus delegate at the end of transaction. It contains all necessary information needed about the relevant transaction. FinanceResponseInfo inherits from ResponseInfo so it includes the status string and xml dictionary in addition to authorisedAmount, transactionId and the html formatted receipts. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `financialResult`
    *NSInteger* | A numerical representation of a financial status result. **Status** **Value** EFT_FINANC_STATUS_UNDEFINED 0x00 EFT_FINANC_STATUS_TRANS_APPROVED 0x01 EFT_FINANC_STATUS_TRANS_DECLINED 0x02 EFT_FINANC_STATUS_TRANS_PROCESSED 0x03 EFT_FINANC_STATUS_TRANS_NOT_PROCESSED 0x04 EFT_FINANC_STATUS_TRANS_CANCELLED 0x05| -| `isRestarting`
    [*BOOL*] | Indicates whether the card reader is about to restart or not (usually indicated after a software update was received on the card reader).If a restart is indicated then you have 2 seconds to start fetching the logs (before the card reader restarts).After fetching the logs you should disconnect from the card reader and wait for it to be visible again.| -| `authorisedAmount`
    *NSInteger* | In the smallest unit for the given CurrencyCode - for the transaction. ISO 4217 defines number of digits in fractional part of currency for every currency code. Example 1000 in the case where CurrencyCode is "0826" (GBP) the amount would be 10.00 pounds or 1000 pense.| -| `transactionId`
    [*NSString*] | The id of current transaction.| -| `customerReceipt`
    [*NSString*] | Customer receipt in html format.| -| `merchantReceipt`
    [*NSString*] | Merchant receipt in html format.| -| `statusMessage`
    [*NSString*] | A human readable message describing the result of the transaction.| -| `type`
    [*NSString*] | The transaction type represents which type of transaction was done. "SALE" for example.| -| `finStatus`
    [*NSString*] | The financial status describes the conclusion of the transaction as received from the card reader. "AUTHORISED" for example.| -| `requestedAmount`
    [*NSString*] | The requested amount is the payment amount sent in the original request to the card reader, i.e. the amount which was to charge the card with.| -| `gratuityAmount`
    [*NSString*] | The gratuity amount is an additional amount added to the requested payment amount which represents additional fee added to the requested amount. This is used when the card reader is supporting the tipping functionality. An example: A sale is started with the amount 1000 and the card reader is set to support tipping. The card reader asks if a tip should be applied by the customer. The customer inputs an additional amount as a tip, lets say 100. The card is then charged for the requested amount, 1000, as well as the additional gratuity amount, 100. The result will be that the card will be charged for 1100. A calculated gratuity percentage will also be returned.| -| `gratuityPercentage`
    [*NSString*] | The gratuity percentage is used to calculate an additional amount to the requested amount. The card reader calculates that amount, rounded up to the closest whole number. This is used when the card reader is supporting the tipping functionality. An example: A sale is started with the amount 1000 and the card reader is set to support tipping. The card reader asks if a tip should be applied by the customer. Instead of the customer adding a value he selects the percentage of the requested amount to be applied as a tip, lets say 10%. The card is then charged for the requested amount, 1000, as well as the additional gratuity percentage, 10%. The result will be that the card will be charged for 1100. A calculated gratuity amount will also be returned.| -| `totalAmount`
    [*NSString*] | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| -| `currency`
    [*NSString*] | The currency used in this transaction.| -| `eFTTransactionID`
    [*NSString*] | The EFT (electronic funds transfer) transaction id is a unique GUID from the servers which is linked to this transaction in order to search for a particual transaction. This id is used if a transaction is to be reversed.| -| `originalEFTTransactionID`
    [*NSString*] | The original EFT (electronic funds transfer) transaction id is a unique GUID previously received from the servers in order to reverse a transaction. This id is sent with the new eFTTransactionID in order to reference the original transaction. An example: A transaction is made. An eFTTransactionID is received. That transaction has to be reversed. A new transaction is started, now a reverse transaction, with the previously received eFTTransactionID as a parameter in the transaction. In the end result there will be a new eFTTransactionID, for the reverse transaction, and an originalEFTTransactionID referencing the original transaction.| -| `eFTTimestamp`
    [*NSString*] | The eFTTimestamp represents the time when the transaction was done. This time is set by the device communicating to the card reader when the connection is established to the card reader.| -| `authorisationCode`
    [*NSString*] | If the transaction was authorised the value represented can be used to search for a transaction in our system.| -| `verificationMethod`
    [*NSString*] | The verification method represents the card holder verification method used to allow the payment. "PIN" for an example.| -| `cardEntryType`
    [*NSString*] | The card entry type is the method the card information was input to card reader. "ICC" for an example represents "Integrated Circuit Card" i.e. the information was read from the chip of the card.| -| `cardSchemeName`
    [*NSString*] | The scheme which was used when the transaction was made. (VISA, Mastercard, etc...)| -| `errorMessage`
    [*NSString*] | If there was an error during the transaction it is represented here in a human readable text.| -| `customerReference`
    [*NSString*] | If a customer reference was added, as an optional parameter, when the transaction was started. It is received here, unaltered. The customer reference can be used to reference in internal systems.| -| `budgetNumber`
    [*NSString*] | If a budget number was added, as an optional parameter, when the transaction was started. It is received here, unaltered. The budget number can be used to split payments over a period of months.| -| `recoveredTransaction`
    [*NSString*] | This flag is true if the transaction result is from a previous transaction which failed to get sent from the card reader, false otherwise. In the case that the communication between the device and the card reader breaks down, the card reader will attempt to send the result of the previous transaction as an immediate reply when the next transaction is started. If this happens the transaction is flagged as a "RecoveredTransaction". This should be displayed very well in the UI since this is *NOT* the result from the transaction just started.| -| `cardTypeId`
    [*NSString*] | The card type id is an identifier inside the Handpoint gateway which represents what kind of card was used. "U015" for an example represents SAS Airline-Systems in our systems.| -| `chipTransactionReport`
    [*NSString*] | If present, a full EMV report by the card reader on the Card and Terminal involved in the transaction.| -| `deviceStatus`
    [*NSString*] | Gets the device status.| -| `dueAmount`
    [*NSString*] | If there's still a part of the amount to be paid.| -| `balance`
    [*NSString*] | The balance of the Cardholder's cards if the bank/acquirer supports it.| -| `CardToken`
    [*String*] | Gets the card token if it's available, null otherwise.| - - -### ScannerEventResponseInfo{#26} - -`ScannerEventResponseInfo` - -A ScannerEventResponseInfo is passed to the responseScannerEvent delegate during scanner mode when a scan is detected. It contains all necessary information needed about the relevant operation. ScannerEventResponseInfo inherits from ResponseInfo so it includes the status string and xml dictionary in addition to scanCode string. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `statusCode`
    *int* | A numerical representation of the status.| -| `status`
    [*Status as NSString*](#45) | Financial transaction status message.| -| `xml`
    [*XML as NSDictionary*](#46) | Feedback with xml details about transaction from the card reader.| -| `scanCode`
    *NSString* | The code that was scanned.| - -### ScannerDisabledResponseInfo{#27} - -`ScannerDisabledResponseInfo` - -The info object contains information about the scanner operation. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `statusCode`
    *int* | A numerical representation of the status.| -| `status`
    [*Status as NSString*](#45) | Financial transaction status message.| -| `xml`
    [*XML as NSDictionary*](#46) | Feedback with xml details about transaction from the card reader.| - -### LogInfo{#28} - -`LogInfo` - -A LogInfo object is passed to the ResponseLogInfo delegate when logs have been downloaded from the card reader. - -**Properties** - -| Property | Description | -| ----------- | ----------- | -| `statusCode`
    *int* | A numerical representation of the status.| -| `status`
    [*Status as NSString*](#45) | Financial transaction status message.| -| `xml`
    [*XML as NSDictionary*](#46) | Feedback with xml details about transaction from the card reader.| -| `log`
    *NSString* | String containing the logging information.| - -### eLogLevel{#13} - -`eLogLevel` - -An enum describing the different levels of logging used in the SDK and in the device. - -**Possible values** - -`eLogNone` `eLogError` `eLogInfo` `eLogFull` `eLogDebug` - -### Transaction Details{#46} - -`XML as NSDictionary` - -The contents of the xml property depend on which type of operation the card reader is responding to. Listed below are all possible keys in the dictionary. Note that not all fields are included all the time. - -### Dictionary keys: - -**StatusMessage** -*** -A human readable description for the returned Status. - -**TransactionType** -*** -The type of transaction performed: UNDEFINED, SALE, VOID_SALE, REFUND, VOID_REFUND, CANCEL_SALE, CANCEL_REFUND - -**FinancialStatus** -*** -The result of the transaction: UNDEFINED, APPROVED, DECLINED, PROCESSED, FAILED, CANCELLED - -Description of the different financial statuses: - -| Parameter | Notes | -| ----------- | ----------- | -| `UNDEFINED`
    | Any Financial Status other than the below mentioned financial statuses will be `UNDEFINED`. UNDEFINED means that the SDK couldn't get a response from the Gateway. An automatic cancellation service will try to cancel the transaction in case it was approved. | -| `AUTHORISED`
    | The transaction (Sale, Refund,...) has been authorised. Consider this value as "successful". | -| `DECLINED`
    | The transaction has been declined by the acquirer or issuer. | -| `PROCESSED`
    | The `update` operation was successful.| -| `FAILED`
    | Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. | -| `CANCELLED`
    | The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | -| `PARTIAL_APPROVAL`
    | A partial approval is the ability to partially authorize a transaction if the cardholder does not have the funds to cover the entire cost on their card. The merchant can obtain the remainder of the purchase amount in another form of payment. `PARTIAL_APPROVAL` is **only** applicable to the United States market. | - - -**RequestedAmount** -*** -The amount requested by the POS, as requested by the POS (i.e. no decimal point). - -**GratuityAmount** -*** -The gratuity amount entered by the cardholder, if any. - -**GratuityPercentage** -*** -The gratuity amount, as a percentage of the requested amount. - -**TotalAmount** -*** -The total of the gratuity and requested amount. - -**TransactionID** -*** -The transaction number used for this transaction, as maintained by the Eft Client. - -**EFTTransactionID** -*** -The EFT reference, given by the system, to make the transaction unique. - -**OriginalEFTTransactionID** -*** -The original EFT reference, given by the POS, as part of a VOID_SALE or a VOID_REFUND transaction. - -**EFTTimestamp** -*** -The date and time of the transaction, in ISO format (YYYYMMDDHHmmSS). - -**AuthorisationCode** -*** -The transaction authorization code, as given by the system. - -**CVM** -*** -The Cardholder Verfication Method: UNDEFINED, SIGNATURE, PIN, PIN_SIGNATURE, FAILED, NOT_REQUIRED - -**CardEntryType** -*** -The card data acquisition type: UNDEFINED, MSR, ICC, CNP - -**CardSchemeName** -*** -The card, reported, scheme name. - -**CardTypeId** -*** -The ID of the Card Type. - -**SerialNumber** -*** -The serial number of the PED. - -**BatteryStatus** -*** -A number, followed by the % sign, which indicates current charge level of the battery. - -**BatterymV** -*** -An integer, which represent the batter charge, in mV. - -**BatteryCharging** -*** -Indicates whether the battery is charging, or not. Values are true or false. - -**ExternalPower** -*** -Indicates whether the PED is connected to an external power source (e.g. a AC adapter). Values are true or false. - -**ApplicationName** -*** -The name of the application running on the PED. - -**ApplicationVersion** -*** -A version string of the form major.minor.build”(e.g. 1.2.118). - -**ErrorMessage** -*** -Description of the error, if any. - -**RecoveredTransaction** -*** -Indicates that the transaction result is a recovered transaction. The key is only included if value is true. - -### CmdIds - -`card reader Status messages` - -Status messages received from card reader: - -### Possible values - -`EFT_PP_STATUS_SUCCESS` -`EFT_PP_STATUS_INVALID_DATA` -`EFT_PP_STATUS_PROCESSING_ERROR` -`EFT_PP_STATUS_COMMAND_NOT_ALLOWED` -`EFT_PP_STATUS_NOT_INITIALISED` -`EFT_PP_STATUS_CONNECT_TIMEOUT` -`EFT_PP_STATUS_CONNECT_ERROR` -`EFT_PP_STATUS_SENDING_ERROR` -`EFT_PP_STATUS_RECEIVING_ERROR` -`EFT_PP_STATUS_NO_DATA_AVAILABLE` -`EFT_PP_STATUS_TRANS_NOT_ALLOWED` -`EFT_PP_STATUS_UNSUPPORTED_CURRENCY` -`EFT_PP_STATUS_NO_HOST_AVAILABLE` -`EFT_PP_STATUS_CARD_READER_ERROR` -`EFT_PP_STATUS_CARD_READING_FAILED` -`EFT_PP_STATUS_INVALID_CARD` -`EFT_PP_STATUS_INPUT_TIMEOUT` -`EFT_PP_STATUS_USER_CANCELLED` -`EFT_PP_STATUS_INVALID_SIGNATURE` -`EFT_PP_STATUS_WAITING_CARD` -`EFT_PP_STATUS_CARD_INSERTED` -`EFT_PP_STATUS_APPLICATION_SELECTION` -`EFT_PP_STATUS_APPLICATION_CONFIRMATION` -`EFT_PP_STATUS_AMOUNT_VALIDATION` -`EFT_PP_STATUS_PIN_INPUT` -`EFT_PP_STATUS_MANUAL_CARD_INPUT` -`EFT_PP_STATUS_WAITING_CARD_REMOVAL` -`EFT_PP_STATUS_TIP_INPUT` -`EFT_PP_STATUS_SHARED_SECRET_INVALID` -`EFT_PP_STATUS_SHARED_SECRET_AUTH` -`EFT_PP_STATUS_WAITING_SIGNATURE` -`EFT_PP_STATUS_CONNECTING` -`EFT_PP_STATUS_SENDING` -`EFT_PP_STATUS_RECEIVEING` -`EFT_PP_STATUS_DISCONNECTING` -`EFT_PP_STATUS_PIN_INPUT_COMPLETED` -`EFT_PP_STATUS_POS_CANCELLED` -`EFT_PP_STATUS_REQUEST_INVALID` -`EFT_PP_STATUS_CARD_CANCELLED` -`EFT_PP_STATUS_CARD_BLOCKED` -`EFT_PP_STATUS_REQUEST_AUTH_TIMEOUT` -`EFT_PP_STATUS_REQUEST_PAYMENT_TIMEOUT` -`EFT_PP_STATUS_RESPONSE_AUTH_TIMEOUT` -`EFT_PP_STATUS_RESPONSE_PAYMENT_TIMEOUT` -`EFT_PP_STATUS_ICC_CARD_SWIPED` -`EFT_PP_STATUS_REMOVE_CARD` -`EFT_PP_STATUS_SCANNER_IS_NOT_SUPPORTED` -`EFT_PP_STATUS_SCANNER_EVENT` -`EFT_PP_STATUS_BATTERY_TOO_LOW` -`EFT_PP_STATUS_ACCOUNT_TYPE_SELECTION` -`EFT_PP_STATUS_BT_IS_NOT_SUPPORTED` -`EFT_PP_STATUS_PAYMENT_CODE_SELECTION` -`EFT_PP_STATUS_PARTIAL_APPROVAL` -`EFT_PP_STATUS_AMOUNT_DUE_VALIDATION` -`EFT_PP_STATUS_INVALID_URL` -`EFT_PP_STATUS_WAITING_CUSTOMER_RECEIPT` -`EFT_PP_STATUS_PRINTING_MERCHANT_RECEIPT` -`EFT_PP_STATUS_PRINTING_CUSTOMER_RECEIPT` -`EFT_PP_STATUS_WAITING_HOST_MSG_TO_HOST` -`EFT_PP_STATUS_WAITING_HOST_MSG_RESP` -`EFT_PP_STATUS_INITIALISATION_COMPLETE` - - -### Status strings{#45} - -`Status as NSString` - -An NSString containing the status message - can be one of the following: - -### Possible values - -`Success` -`Invalid data` -`Processing error` -`Not allowed` -`Not initialized` -`Connect timeout` -`Connect error` -`Sending error` -`Receiveing error` -`No data available` -`Transaction not allowed` -`Unsupported currency` -`No host available` -`Card reader error` -`Card reading failed` -`Invalid card` -`Input timeout` -`User cancelled` -`Invalid signature` -`Waiting card` -`Card inserted` -`Application selection` -`Application confirmation` -`Amount validation` -`PIN input` -`Manual card input` -`Waiting card removal` -`Tip input` -`Shared secret invalid` -`Connecting` -`Sending` -`Receiving` -`Disconnecting` -`PIN entry completed` -`Merchant cancelled the transaction` -`Request invalid` -`Card cancelled the transaction` -`Blocked card` -`Request for authorisation timed out` -`Request for payment timed out` -`Response to authorisation request timed out` -`Response to payment request timed out` -`Please insert card in chip reader` -`Remove the card from the reader` -`This device does not have a scanner` -`Scanner is not supported` -`Scanner event` - -## Process details - -The following table contains result codes that can occur in the COMMAND response STATUS field (see section 1.3 above). - -In addition the following table contains the text information presented in the StatusMessage field that is part of the FinancialTransactionResponse Xml response object. - -All values are in hex in the following table. - -| Status ID | Value | StatusMessage| Details | -| ----------- | ----------- |----------- | ----------- | -| EFT_SUCCESS | 0001| One of the following: "" (an empty string) "AUTH CODE #" "REFUND ACCEPTED" "REVERSAL ACCEPTED"|Operation completed successfully. No further actions required.| -| EFT_INVALID_DATA | 0002|"Invalid data"|Invalid COMMAND request object, from the POS App, at the start of an operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_PROCESSING_ERROR |0003| "Processing error"| An unexpected error occurred during processing. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_COMMAND_NOT_ALLOWED| 0004| "Command not allowed"| The card reader is currently busy processing another command. Please retry the operation once the current operation has completed.|| -|EFT_NOT_INITIALISED |0005 |"Device is not initialized"| The current operation can’t be completed because there is a pending software update that must be applied before processing can continue. Please retry the operation after the card reader has restarted itself.| -|EFT_CONNECT_TIMEOUT |0006 |"Connection time out detected"| The back end connection timed out during an update. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_CONNECT_ERROR |0007 |"Connection error" |It was not possible to establish a connection to the back end system during an update operation. Please retry the operation. If the issue persists please contact technical support and provide card reader logs.| -|EFT_SENDING_ERROR |0008 |"Send error" |A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| -|EFT_RECEIVING_ERROR |0009| "Receiving error"| A failure was detected during communication with the back end system. If a SALE or a REFUND transaction was in progress when this occurred then you MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once verified please retry the operation.| -|EFT_NO_DATA_AVAILABLE |000A| "No data available"| The POS App is trying to fetch the card reader log file but there is no data stored in the log file. If logs are required then please set the log level to an appropriate value and retry the operation.| -|EFT_TRANS_NOT_ALLOWED |000B| "Transaction not allowed"| `Currently not used`| -|EFT_UNSUPPORTED_CURRENCY| 000C| "Currency not supported"| A currency has been selected that the card reader has not been configured for. Please select the correct currency and retry the operation. Alternatively, please contact technical support and ask for the specific currency to be supported.| -|EFT_NO_HOST_AVAILABLE| 000D |"No host configuration found"| An update was initiated but the card reader could not find any host information for the back end system, even though it otherwise contains valid configuration. This is indicative of an invalid `hostBlock` block with in the `HostList` block in this device configuration, which was placed on the card reader during a previous update. Please contact technical support and provide card reader logs and ask for a replacement device. The card reader will be unable to update itself and must be replaced.| -|EFT_CARD_READER_ERROR |000E |"Card reader error"| Error detected in the chip reader or the magnetic stripe reader. Please retry the operation. If the issue persists please contact technical support and provide them with the card reader logs as well as asking for a replacement reader.| -|EFT_CARD_READING_FAILED| 000F| "Failed to read card data"| The card reader could not read any data from the card. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| -|EFT_INVALID_CARD |0010 |"INVALID CARD" |The card reader detected invalid card data. Please retry the operation. If the issue persists the card may be faulty, please try another card. If the issue still persists the card reader may require replacement, please contact technical support.| -|EFT_INPUT_TIMEOUT |0011| "Timeout waiting for user input"| The card reader timed out while waiting for a user action. No further actions required.| -|EFT_USER_CANCELLED |0012| "TRANSACTION VOID" "User cancelled the transaction" |The current operation was cancelled by card holder. No further actions required.| -|EFT_SHARED_SECRET_INVALID| 001D| "Shared Secret invalid"| The card reader believes that the POS App has an incorrect shared secret. No financial operations will be possible (e.g. SALE, REFUND). Please type the correct shared secret into the POS App or contact technical support for further assistance.| -|EFT_SHARED_SECRET_AUTH |001E |"Authenticating POS"| The card reader is about to challenge the POS App for a correct shared secret. No further actions are required.| - | REPORT STATUS SPECIFIC| -|EFT_INVALID_SIGNATURE |0013| "TRANSACTION VOID"| The merchant indicated that the signature provided by the card holder was invalid. No further actions are required.| -|EFT_WAITING_CARD |0014| "Waiting for card" |The card reader is waiting for a card to be inserted into the chip reader or for a card to be swiped (only applies to card readers with external MSR). Insert or swipe a card to continue with the transaction.| -|EFT_CARD_INSERTED |0015| "Card detected" |`Currently not used`| -|EFT_APPLICATION_SELECTION |0016| "Waiting for application selection" |The card reader is waiting for the card holder to select a card application to be used for the transaction. The card holder must select an application for use (e.g. VISA, MASTERCARD, etc.) and should then press either the OK button to continue. Press the C/Cancel button to abort the transaction.| -|EFT_APPLICATION_CONFIRMATION| 0017| "Waiting for application confirmation"| The card reader is waiting for the card holder to confirm that the displayed card application should be used for the transaction. The card holder should press either the OK or the C/Cancel button.| -|EFT_AMOUNT_VALIDATION| 0018 |"Waiting for amount validation"| The card reader is waiting for the card holder to confirm that the amount presented is correct. The card holder should press either the OK or the C/Cancel button.| -|EFT_PIN_INPUT |0019| "Waiting for PIN entry"| The card reader is waiting for the card holder to enter his/her PIN. The card holder should enter his PIN and then press the OK button to continue. For PIN bypass press the OK button without entering any PIN digits (this will trigger signature fallback). Press the C/Cancel button to abort the transaction. Note: It is not possible to cancel this operation from the POS App.| -|EFT_MANUAL_CARD_INPUT |001A| "Waiting for manual card data"| `Currently not used`| -|EFT_WAITING_CARD_REMOVAL| 001B| "Waiting for card removal"| A card was detected in the card reader at the start of a transaction, presumably left there from a previous transaction. Please remove the card and restart the operation.| -|EFT_TIP_INPUT |001C| "Waiting for gratuity" |The card reader is waiting for the card holder to enter/confirm tip/gratuity information.| -|EFT_WAITING_SIGNATURE |001F| "Waiting for signature" |The card reader is waiting for confirmation from the merchant that the card holder signature is valid. The merchant should press either the Accepted or Declined/Cancel in the POS App. Pressing Cancel or OK on the card reader will not have any effect.| -|EFT_WAITING_HOST_CONNECT |0020| "Connecting to host"| The card reader is establishing a connection to the back end system. No further actions are required.| -|EFT_WAITING_HOST_SEND| 0021 |"Sending data to host" |The card reader is sending data to the back end system. No further actions are required.| -|EFT_WAITING_HOST_RECEIVE| 0022| "Waiting for data from host" |The card reader is waiting for data from to the back end system. No further actions are required.| -|EFT_WAITING_HOST_DISCONNECT| 0023| "Disconnecting from host"| The card reader is disconnecting from the back end system. No further actions are required.| -|EFT_PIN_INPUT_COMPLETED| 0024| "PIN entry completed"| PIN entry has been completed. No further actions required.| -|EFT_POS_CANCELLED |0025| "TRANSACTION VOID" |The current operation was cancelled by merchant. No further actions required.| -|EFT_REQUEST_INVALID| 0026| "Request invalid"| Card not allowed with this transaction type.| -|EFT_CARD_CANCELLED |0027| "TRANSACTION VOID"| The chip on the card cancelled the transaction. No further actions required.| -|EFT_CARD_BLOCKED |0028| |"CARD BLOCKED" |The card used in the transaction is blocked. Please retry the transaction with a non-blocked card.| -|EFT_REQUEST_AUTH_TIMEOUT |0029| "Request for authorisation timed out"| Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_REQUEST_PAYMENT_TIMEOUT| 002A| "Request for payment timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_RESPONSE_AUTH_TIMEOUT |002B| "Response to authorisation request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the authorization phase. Please make sure the phone/pc has an internet connection and then retry the operation. If the problem persists then please contact technical support. Note: You may be asked to provide the card reader logs.| -|EFT_RESPONSE_PAYMENT_TIMEOUT| 002C| "Response to payment request timed out" |Indicates that the card reader detected a communication failure between itself and the back end system during the payments phase. You MUST contact technical support and verify whether the transaction went through or not. If you fail to do so then you may be liable for any costs incurred due to any double charges. Note: You may be asked to provide the card reader logs. Once you have verified that the transaction did not go through then please make sure the phone/pc has an internet connection and then retry the operation.| -|EFT_ICC_CARD_SWIPED| 002D| "Please insert card in chip reader" |`Currently not used`| -|EFT_REMOVE_CARD |002E| "Remove the card from the reader" |`Currently not used`| -|EFT_SCANNER_IS_NOT_SUPPORTED| 002F| "This device does not have a scanner" |Bar-code scanner hardware is not present on this card reader. No further actions are required.| -|EFT_SCANNER_EVENT| 0030| "" |Bar-code data was just read with the bar-code scanner and returned to the POS App. No further actions are required.| -|EFT_BATTERY_TOO_LOW| 0031| "Operation cancelled, the battery is too low. Please charge."| An operation was started, but the battery charge level is too low to complete the operation. Please recharge the card reader.| -|EFT_ACCOUNT_TYPE_SELECTION| 0032| "Waiting for account type selection"| The card reader is waiting for the card holder to choose an account type for the transaction (i.e. default, credit, cheque/debit or savings).| \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosdevicemanagement.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosdevicemanagement.md index 98f35b7..2b3b8eb 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosdevicemanagement.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosdevicemanagement.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 id: iosdevicemanagement --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosevents.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosevents.md index 3cadb49..a50716c 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosevents.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosevents.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 10 id: iosevents --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosinstallation.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosinstallation.md index 4310562..9c7560b 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosinstallation.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosinstallation.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 id: iosinstallation --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md index 1b6f84f..c913b26 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosintegration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 id: iosintegration --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosmigration.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosmigration.md index e4f5879..d99260b 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosmigration.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosmigration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 id: iosmigration --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosobjects.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosobjects.md index 9f54d5e..f603e39 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosobjects.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosobjects.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 id: iosobjects --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosprocessing.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosprocessing.md index 6d32c3e..ea2885b 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosprocessing.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosprocessing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 id: iosprocessing --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md new file mode 100644 index 0000000..5ac696c --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md @@ -0,0 +1,21 @@ +--- +sidebar_position: 2 +id: iosreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + +## 4.0.1 +**Fixes**: + - Multi MID fix for INTERAC and POSTBRIDGE acquirers. + +## 4.0.0 +**Features**: + - Support for Multi MID and HiPro scanner fixes. + diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iossdkprocessing.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iossdkprocessing.md index f754bb5..b614ac1 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iossdkprocessing.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iossdkprocessing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 id: iossdkprocessing --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iostransactions.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iostransactions.md index b88e917..c042a85 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iostransactions.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iostransactions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 id: iostransactions --- diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosdevicemanagement.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosdevicemanagement.md new file mode 100644 index 0000000..2b3b8eb --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosdevicemanagement.md @@ -0,0 +1,313 @@ +--- +sidebar_position: 9 +id: iosdevicemanagement +--- + + + +# Terminal Management + +## Update terminal{#47} + +`financeInit` Method + +The update operation checks for available software or configuration update for the payment terminal and initiates a download if needed. + +**Code example** + +````objectivec +//financeInit +//Initializes the card reader and updates config. +-(IBAction)updateCardReader +{ + [heftClient financeInit]; +} +```` + +**Events invoked** + +[**responseStatus**](iosevents.md#14) + +Invoked during a transaction with different statuses from the payment terminal. +*** + +[**responseError**](iosevents.md#15) + +Invoked when an error response happens. +*** + +[**responseFinanceStatus**](iosevents.md#16) + +Invoked when the payment terminal finishes processing the transaction. +*** +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| This method always returns YES| + +## Shared Manager{#11} + +`sharedManager` Method + +Provides access to the heftManager. The heft manager is used for discovering devices and creating a HeftClient with a connection to selected payment terminals. + +**Code example** + +````objectivec +//SharedManager +//Provides access to the heftManager + +//Create an instance of the shared manager at set it's delegate +HeftManager* heftManager = [HeftManager sharedManager]; +heftManager.delegate = self; +```` + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| [**HeftManager**](iosobjects.md#19)| The heftManager instance| + + + + + +## Client for device (NSString){#12} + +`clientForDevice` Method + +Creates a HeftClient object. If a connection is successful, the HeftClient object is returned in the didConnect event. All transactions are done using the heftClient. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
    *NSInteger* | The payment terminal to connect to.| +| `sharedSecret` Required
    *NSString* | Shared secret only known by the merchant and Handpoint.| +| `aDelegate` Required
    *BOOL* | The HeftStatusReportDelegate for the HeftClient to report to.| + + +**Code example** + +````objectivec +//clientForDevice:sharedSecretString:delegate: +//Creates a HeftClient object(connection to device) +NSString* sharedSecret = @"0102030405060708091011121314151617181920212223242526272829303132"; +-(void)connectToFirstCardReaderWith:(NSString*)sharedSecret; +{ + //Try to connect to the first payment terminal in the array + [heftManager clientForDevice:[[heftManager devicesCopy] objectAtIndex:0] sharedSecretString:sharedSecret delegate:self]; + //Client calls the didConnect delegate function if successful +} +```` + +**Events invoked** + +[**didConnect**](iosevents.md#20) + +Called when a connection to specified device was created. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| YES if operation starts successfully| + + + + +## Start Discovery {#32} + +`startDiscovery` Method + +Displays a list of available accessory devices in a modal window. + +**Code example** + +````objectivec +//startDiscovery +//Starts the BT discovery process +-(void)startDiscovery; +{ + [heftManager startDiscovery]; + //Start search activity indicator or other desired functions +} +```` + +## Set log level{#33} + +`logSetLevel` Method + +Sets the log level of the payment terminal. There are four levels of logging: none, info, full, debug. Setting the log level means that relevant information concerning the application operation will be stored. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
    [eLogLevel](iosobjects.md#13) | eLogLevel available types: eLogNone, eLogInfo, eLogFull, eLogDebug| + +**Code example** + +````objectivec +//logSetLevel: +//Sets the log level of the card reader. +-(void)disableCardReaderLogs +{ + [heftClient logSetLevel:eLogNone]; +} +-(void)enableCardReaderDebugLogs +{ + [heftClient logSetLevel:eLogDebug]; +} +```` + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| This method always returns YES| + + + + + + +## Fetch logs{#34} + +`logGetInfo` Method + +Retrieves the logging info. Returns them in the responseLogInfo event. + +**Code example** + +````objectivec +//logGetInfo +//Retrieves the logging info. +-(void)getLogsFromCardReader +{ + [heftClient logGetInfo]; +} +```` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| This method always returns YES| + +## Reset logs{#35} + +`logReset` Method + +Clears the logging information stored so far. + +**Code example** + +````objectivec +//logReset +//Clears the logging information stored so far +-(void)clearLogs +{ + [heftClient logReset]; +} +```` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| This method always returns YES| + +## Enable scanner{#36} + +`enableScanner` Method + +Switches the payment terminal in scan mode. Only if the card reader supports it. To cancel/stop scan mode, call the cancel method of the heft client. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `multiScan`
    *Boolean* | Yes [default] to activate multiScan mode.
    No to activate singleScan mode.

    Multi-scan mode allows the user to scan until the scan operation is canceled, or a timeout occurs, single-scan mode is active until one scan has occurred then it disables the scan mode.| +| `buttonMode`
    *Boolean* | Yes [default] if buttonMode is on.
    No otherwise.

    If button mode is on then the operator needs to press the scan button to activate the scanner (during scan mode).| +| `timeoutSeconds`
    *NSInteger* | 0 [default] - The payment terminal will determine when scanning should time out.
    x - the scanner will time out if x seconds of inactivity occur.| + +**Code example** + +````objectivec +//enableScanner:multiScan:buttonMode:timeoutSeconds +//Places the card reader in a scan only mode. +//To cancel/stop scan mode call cancel function. +-(IBAction)startScan +{ + [heftClient enableScanner]; +} +-(IBAction)startMultiScan +{ + [heftClient enableScannerWithMultiScan:YES]; +} +```` + +**Events invoked** + +[**responseScannerEvent**](iosevents.md#41) + +Called to inform that a scan has been performed, several calls can be expected. The info object contains scanCode, status and a dictionary (xml). + +## Disable scanner + +`disableScanner` Method + +Disables the scanner, if possible. + +**Code example** + +````objectivec +//disableScanner +//Disable the scanner + -(IBAction)disableScanner +{ +[heftClient disableScanner]; +} +```` + +**Events invoked** + +[**responseScannerDisabled**](iosevents.md#42) + +Called to inform that a scan has been performed, several calls can be expected. The info object contains scanCode, status and a dictionary (xml). + +## Get SDK version + +`getSDKVersion` Method + +Returns the current SDK version as a string. + +**Code example** + +````objectivec +//getSDKVersion +//Log SDK version number + NSLOG(@"SDK version: %@", [heftManager getSDKVersion]; +```` + +## Get SDK build number + +`getSDKBuildNumber` Method + +Returns the current SDK build as a string. + +**Code example** + +````objectivec +//getSDKBuildNumber +//Log SDK build number + NSLOG(@"SDK build: %@", [heftManager getSDKBuildNumber]; +```` \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosevents.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosevents.md new file mode 100644 index 0000000..a50716c --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosevents.md @@ -0,0 +1,333 @@ +--- +sidebar_position: 10 +id: iosevents +--- + + + +# Events + +### didConnect{#20} + +`didConnect` Method + +Called when a connection to the client has been established through the method clientForDevice. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `client` Required
    [HeftClient](iosobjects.md#22) | The client object, used to perform transactions and communicate with the payment terminal.| + +**Code example** + +````objectivec +//didConnect: +//Called when a connection to specified device was created. +-(void)didConnect:(id)client +{ + // connected successfully to a device + // assign the client to our heftClient property + heftClient = client; +} +```` + +### didDiscoverFinished {#37} + +`didDiscoverFinished` Method + +When the modal window from startDiscovery is closed then this event is called. + +**Code example** + +````objectivec +//didDiscoverFinished +// This function gets called when discovery is finished +- (void)didDiscoverFinished; +{ + NSLog(@"Discover finished"); + //Stop search activity indicator or other desired functions +} +```` + + +### didFindAccessoryDevice{#38} + +`didFindAccessoryDevice` Method + +Notifies that a new accessory device was found. When a payment terminal is detected this delegate is called. You can take the newDevice object and create a new heft client for that particular terminal or store it in memory to connect to it later. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `newDevice` Required
    [HeftRemoteDevice](iosobjects.md#23) | An object containing a reference to the accessory device.| + +**Code example** + +````objectivec +//didFindAccessoryDevice +//Delegate which notifies that a new accessory device was found. +- (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice +{ + NSLog(@"Found new device"); + //Connect to device or store found device for later. +} +```` + + +### didLostAccessoryDevice{#39} + + +`didLostAccessoryDevice` Method + +Notifies that the accessory device was disconnected. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `oldDevice` Required
    [HeftRemoteDevice](iosobjects.md#23) | An object containing a reference to the accessory device.| + +**Code example** + +````objectivec +//didLostAccessoryDevice +//Delegate which notifies that an accessory device was disconnected +- (void)didLostAccessoryDevice:(HeftRemoteDevice*)oldDevice +{ + NSLog(@"Device disconnected"); + //Remove device from devices array + [heftManager.devicesCopy removeObject:oldDevice]; + //Do some cleanup after disconnecting if necessary + +} +```` + +### responseStatus{#14} + +`responseStatus` Method + +Called to inform about the status of the transaction, several calls can be expected. Several calls to this method happen after a transaction is initiated from the HeftClient to inform about the status of operation. The info object contains a string (status) and a dictionary (xml). + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [ResponseInfo](iosobjects.md#24) | Includes status code, status text and detailed xml.| + +**Code example** + +````objectivec +//responseStatus: +//Called to inform about the status of the transaction +-(void)esponseStatus:(id)info +{ + NSLog(info.status); + NSLog(info.xml.description); +} +```` + +### responseFinanceStatus{#16} + +`responseFinanceStatus` Method + +Notifies that the transaction has completed. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [FinanceResponseInfo](iosobjects.md#25) | Information about current transaction status.| + +**Code example** + +````objectivec +//responseFinanceStatus: +//Called at the end of a transaction to inform about the result of the operation. +-(void)responseFinanceStatus:(id)info +{ + NSLog(info.status); + NSLog(info.customerReceipt); + //print receipts +} +```` + +### responseError{#15} + +`responseError` Method + +Called to inform about the status of the transaction, several calls can be expected. Several calls to this method happen after a transaction is initiated from the HeftClient to inform about the status of operation. The info object contains a string (status) and a dictionary (xml). + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [ResponseInfo](iosobjects.md#24) | The info object contains a string (status) and a dictionary (xml).| + +**Code example** + +````objectivec +//responseError: +//Called when an error happens. +-(void)responseError:(id)info +{ + NSLog(info.status); + NSLog(info.xml.description); +} +```` + +### requestSignature{#17} + +`requestSignature` Method + +Called during a financial operation if a signature from the customer is needed. The requestSignature delegate should be implemented to print out or display the receipt for the customer to sign. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
    *NSString* | The receipt is a html formatted string containing a receipt for the customer to sign.| + +**Code example** + +````objectivec +//requestSignature: +//Is called if a signature from the customer is needed. +-(void)requestSignature:(NSString*)receipt +{ + NSLog(receipt); + //Display buttons to accept or decline customer signature + UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"" message:@"sign?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; + [alert show]; +} +```` + +### cancelSignature{#40} + +`cancelSignature` Method + +Called if the signature request times out. If the payment terminal does not receive an approval for the signature within a certain timeframe, it cancels the transaction and sends a notification to the app. + +**Code example** + +````objectivec +//cancelSignature +//Called if the signature request times out. +-(void)cancelSignature +{ + NSLog(@"Signature request timed out"); +} +```` + +### responseScannerEvent{#41} + +`responseScannerEvent` Method + +Called to inform that a scan has been performed, several calls can be expected. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [ScannerEventResponseInfo](iosobjects.md#26) | The info object contains scanCode, status and a dictionary (xml).| + +**Code example** + +````objectivec +//responseScannerEvent: +//Called to inform that a scan has been performed +-(void)responseScannerEvent:(id)info +{ + NSLog(info.scanCode); //barcode scanned + NSLog(info.xml.description); +} +```` + +### responseScannerDisabled{#42} + +`responseScannerDisabled` Method + +Called to notify that the scanner has been disabled. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [ScannerDisabledResponseInfo](iosobjects.md#27) | The info object contains information about the scanner operation.| + +**Code example** + +````objectivec +//responseScannerDisabled: +//Called to notify that the scanner has been disabled. +-(void)responseScannerDisabled:(id)info +{ + NSLog(info.status); +} +```` + +### responseLogInfo{#43} + +`responseLogInfo` Method + +Called when logs have been downloaded from the payment terminal by using the logGetInfo method. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [LogInfo](iosobjects.md#28) | The info object has the string property log which holds the log info in text with carriage returns.| + +**Code example** + +````objectivec +//responseLogInfo: +//Called when logs have been downloaded from the card reader by using the logGetInfo method. +-(void)responseLogInfo:(id)info +{ + NSLog(info.log); + //write to log file +} +```` + +### responseRecoveredTransactionStatus{#44} + +`responseRecoveredTransactionStatus` Method + +Notifies that a transaction has been recovered. + +This method is **OPTIONAL** and only required if retrievePendingTransaction is called. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `info` Required
    [*FinanceResponseInfo*](iosobjects.md#25) | Information about the recovered transaction status.

    **If an attempt was made to recover a transaction when none was pending then this parameter WILL be nil.**| + + +**Code example** + +````objectivec +//responseRecoveredTransactionStatus: +//Called when a pending transaction result has been recovered from the payment terminal. +- (void)responseRecoveredTransactionStatus:(id)info{ + if(info != nil) { + if(info.statusCode == EFT_PP_STATUS_SUCCESS) { + NSLog(info.status); + NSLog(info.customerReceipt); + NSLog(info.merchantReceipt); + // print receipts and/or save receipts in the transaction log. + + if(info.financialResult == EFT_FINANC_STATUS_TRANS_APPROVED){ + // Process to recover an authorized transaction result. + } else if(info.financialResult == EFT_FINANC_STATUS_TRANS_DECLINED) { + // Process to recover a declined transaction result. + } + } else if(info.statusCode != EFT_PP_STATUS_NO_DATA_AVAILABLE) { + // some other error was detected while waiting for a pending transaction result. + } + } + // else a pending transaction result was not found. +} +```` diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosinstallation.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosinstallation.md new file mode 100644 index 0000000..9c7560b --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosinstallation.md @@ -0,0 +1,98 @@ +--- +sidebar_position: 5 +id: iosinstallation +--- + + + + +# SDK Installation + + +## CocoaPods + +[CocoaPods](https://cocoapods.org/) is a dependency manager for Cocoa projects. You can install it with the following command: + +```` +$ gem install cocoapods +```` + +If you don't have a `Podfile` yet: + +```` +$ pod init +```` + +To integrate the HandpointSDK into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```` +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' +use_frameworks! + +target 'your_target' do + pod 'HandpointSDK', '~> 3.2.3' +end +```` + +Then, run the following command: + +```` +$ pod install +```` + +## Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](https://brew.sh/) using the following command: + +``` +$ brew update +$ brew install carthage +``` + +To integrate the HandpointSDK into your Xcode project using Carthage, specify it in your `Cartfile`: + +```` +github "handpoint/HandpointSDK-iOS" +````` + +Run `carthage update` to build the framework and drag the built `HandpointSDK.framework` into your Xcode project. + +## Manually + +If you'd rather handle the dependency manually there are three different approaches to include the ```HandpointSDK``` in your project: + +### Prebuilt static library + +Download the latest pre-built static library from [Github](https://github.com/handpoint/HandpointSDK-iOS) and refer to the readme.md for the installation steps. + +### Building the project yourself + +Download the latest version from the master branch: + +``` +$ git clone https://github.com/handpoint/HandpointSDK-iOS.git +``` + +Alternatively you can add it as a git [submodule](https://git-scm.com/docs/git-submodule): + +``` +$ git submodule add https://github.com/handpoint/HandpointSDK-iOS.git +``` + +### Framework + +You'll find the dynamic framework project called `HandpointSDK.xcodeproj` at the root of the repo. + +### Static Library + +You'll find the static library project called `headstart.xcodeproj` under the `Library` folder. + +We **strongly** discourage you from building this project yourself. + +This project contains several targets, you need to build the aggregated target `device-simulator Release` + +This target produces a .zip file in the same directory as the `headstart.xcodeproj` file containing both the library and the simulator library. + diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosintegration.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosintegration.md new file mode 100644 index 0000000..b42abaf --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosintegration.md @@ -0,0 +1,188 @@ +--- +sidebar_position: 6 +id: iosintegration +--- + + +# Integration Guide + +**The SDK supports the following connection methods:** + +1. **[Bluetooth (HiLite)](#filesiniOSSDK)** +2. **[Lightning (HiPro)](#filesiniOSSDK)** + +## Files in iOS SDK {#filesiniOSSDK} + +### If you're using the library/Cocoapods: + +- **HandpointAll.h**: #import this header file into your classes. +- **libheft.a**: The SDK library. + +### If you're using the framework/Carthage: + +- ** HandpointSDK.h**: #import this header file into your classes. +- **HandpointSDK.framework**: The SDK library. + +The SDK also includes a simulator, a library configured to simulate a payment terminal - intended for early development of an user interface. To use it, just link the libheft.a file in the HeftSimulatorLibrary folder, instead of the actual SDK library. + +## Development settings for the SDK + +- **Dependencies**:The Heft library depends on the``` ExternalAccessory``` and ``` libc++.dylib``` frameworks included with the iOS SDK. These frameworks and the **libheft.a** SDK library itself need to be linked to your project for the Handpoint interface to work properly. + +- **Communication protocol**: Your application needs to support the card reader communication protocol. For this reason, the ```com.datecs.pinpad``` string needs to be added to the ```Supported external accessory protocols``` in the **.plist file**: + +````xml + UISupportedExternalAccessoryProtocols + + com.datecs.pinpad + +```` + +- **Background mode support**: Your application needs to support connection to external devices when in the background. For this reason, in the "Capabilities" section of the project settings, the **Background Modes** profile needs to be ON, and the ```External accessory communication ``` option must be checked. This is equivalent to adding the following entry in the .plist file: + + +````xml + UIBackgroundModes + + external-accessory + +```` + +- **C++ linker flag**: A part of the library is written in c++ therefore the **-lc++ linker flag** needs to be set. Add it under "Other Linker Flags" under the "Linking" section of your projects settings "Build Settings" tab. +- **Other settings**: To prevent the warning "file was built for archive which is not the architecture being linked (armv7s)", **set Build Active Architecture Only** to YES. + + +## Usage summary + +Any application using the Handpoint SDK should follow these steps: + +1. Define a class that implements the** HeftDiscoveryDelegate **protocol. +This class defines the behavior of the app when discovery related events are received from the SDK. +2. Define a class that implements the **HeftStatusReportDelegate** protocol (it can be the same as above). +This class defines the behavior of the app when connection and transaction related events are received from the SDK +3. Get a reference to the HeftManager singleton and assign your HeftDiscoveryDelegate instance as delegate. +4. If device is available through BT connection, start the discovery process by calling the** startDiscovery** function of the HeftManager and recover a list of the discovered devices by calling the **connectedCardReaders **function of the HeftManager. +5. If device is using a Lightning connector (HiPro devices), recover the device by directly calling the **connectedCardReaders** function of the HeftManager. +6. Connect to a device by calling the **clientForDevice** function of the HeftManager. +7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. +8. From this point, start processing transactions and have fun! + +## Usage details + +1. Define a class that implements the ** HeftDiscoveryDelegate **protocol. +This class will define the behavior of the application when discovery related events are received from the SDK. + +````objectivec + @interface MyDiscoveryDelegate () + @implementation MyDiscoveryDelegate +```` + +2. Define a class that implements the** HeftStatusReportDelegate **protocol (it can be the same as above). +This class will define the behavior of the application when connection and transaction related events are received from the SDK. + +````objectivec + @interface MyStatusReportDelegate () + @implementation MyStatusReportDelegate +```` + +3. Get a reference to the HeftManager singleton in SDK by calling the **sharedManager** class method. +Assign your HeftDiscoveryDelegate instance as delegate of the manager. + +````objectivec + MyDiscoveryDelegate* myDiscoveryDelegate = [[alloc MyDiscoveryDelegate] init]; + HeftManager* manager = [HeftManager sharedManager]; + manager.delegate = myDiscoveryDelegate; +```` + +4. If device is available through BT connection, start the discovery process by calling the **startDiscovery** function of the HeftManager. + +````objectivec + [manager startDiscovery]; +```` + +When a device is selected by the user in the “Select device” popup window, the **didFindAccessoryDevice** function of the HeftDiscoveryDelegate is invoked. + +````objectivec + - (void)didFindAccessoryDevice:(HeftRemoteDevice*)newDevice + { + NSLog(@"Found new device"); + //Connect to found device or store it for later + } +```` + +When the discovery process is finished, the **didDiscoverFinished** function of the HeftDiscoveryDelegate instance will be invoked. Recover a list of all the discovered devices by calling the **connectedCardReaders** function of the HeftManager. + +````objectivec + - (void)didDiscoverFinished + { + NSMutableDictionary *discoveredDevices = [self.manager connectedCardReaders]; + } +```` + +5. If device is using a Lightning connection (HiPro devices), skip the previous step and recover the device by directly calling the **connectedCardReaders** function of the HeftManager. + +````objectivec +HeftRemoteDevice *lightningDevice = [[self.manager connectedCardReaders] firstObject]; +```` + +6. Connect to a device by calling the **clientForDevice** function of the HeftManager. + +* Expected parameters of this function are: + + - A discovered device (HeftRemoteDevice object). + + - A shared secret. The shared secret is a unique identifier. It is a used to link a merchant with his readers. Each one of your merchants will be assigned a different shared secret so it needs to be a configurable value in your application or backend. If you received a development kit with a card reader, our support team probably sent you a shared secret via email already. + + - A HeftStatusReportDelegate instance, which will be notified of all the events related with the device. + +```` objectivec + // Declare the shared secret (below SS is an example, please put the one sent by our support team) + NSString *sharedSecret =@"0102030405060708091011121314151617181920212223242526272829303132"; + // Connect to reader + [manager clientForDevice:device + sharedSecret:mySharedSecret + delegate:myStatusReportDelegate]; +```` + +7. If connection is successful, the **didConnect** function of the HeftStatusReportDelegate instance will be invoked. Function receives as parameter a HeftClient object, whose reference must be stored since it is the communication bridge to the device we have connected to. + +```` objectivec + - (void)didConnect:(id )client + { + self.heftClient = client; + } +```` + +8. Once connected to the card reader, transactions can be started through the HeftClient object. For example, the next code starts a sale of 100 GBP: + +````objectivec +[self.heftClient saleWithAmount:100 currency:@"GBP" cardholder:YES]; +```` + +9. When a transaction has been initiated (f.ex saleWithAmount), the HeftClient alerts the HeftStatusReportDelegate object by invoking **responseStatus** during the process and **responceFinanceStatus** when the process has finished. + +````objectivec + - (void)responseStatus:(id)info + { + NSLog(@"responseStatus:"); + NSLog(info.status); + NSLog(info.xml.description); + } + + - (void)responseFinanceStatus:(id)info + { + NSLog(@"responseFinanceStatus:"); + NSLog(info.status); + NSLog(info.customerReceipt); + NSLog(info.xml.description); + } +```` + +10. In case you are using the **SDK simulator**, the behavior changes according to the amount of the transaction: + +| **Amount** | **Behavior** | +| ----------- | ----------- | +| 1000 | Declined transaction| +| 2000 | User Cancelled| +| 3000 | Signature Requested| +| Other amount | Approved transaction| \ No newline at end of file diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosintroduction.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosintroduction.md new file mode 100644 index 0000000..64b6b1f --- /dev/null +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: iosintroduction +--- + + +# Introduction + + +

Handpoint offers a basic standalone application allowing your merchants to take payments without being connected to a point of sale software. When the card reader is used in standalone mode, the merchant can simply type in an amount and start processing payments. - The Handpoint standalone application offers a full set of functionalities, from powerful analytics, to end-of-day reports and manual card entry for over the phone transactions.

+ The Handpoint standalone application offers a full set of functionalities, from powerful analytics, to end-of-day reports and MoTo (Mail Order Telephone Order).

standalone terminal
@@ -372,8 +372,7 @@ function TableTerminals() { @@ -653,9 +652,6 @@ function TableTerminals() {

- - -

@@ -692,8 +688,26 @@ function TableTerminals() {
- - +

+
+
+
+ +
+
+
@@ -1329,11 +1343,11 @@ function HighLevelFeatures() {
-

Manual Card Entry / MOTO

+

MOTO

- MOTO (Mail Order / Telephone Order) also called manual card entry is a type of transaction used by merchants to get services paid via telephone, mail, fax, or internet communication. + MOTO (Mail Order / Telephone Order) is a type of transaction used by merchants to get services paid via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged.

From bcbe511d0c34586a60ec1ab472c4d717be04dc7c Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:41:43 +0200 Subject: [PATCH 102/115] Add a8900 description (#134) Added communications row for A8900 --- src/pages/cpdocs.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/cpdocs.js b/src/pages/cpdocs.js index 3eb8d3a..b1fba3f 100644 --- a/src/pages/cpdocs.js +++ b/src/pages/cpdocs.js @@ -900,6 +900,14 @@ function CommunicationTypesTable() { + + PAX A8900 + + + + + + From 89926ddb6711716cc3327d361b772d8303411996 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Tue, 1 Jul 2025 16:48:25 +0200 Subject: [PATCH 103/115] SDK-3901 (#136) Adding Android SDK 7.1010.2 documentation --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 174 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 451 ++++ .../androidtransactions.md | 2027 +++++++++++++++++ ...version-Android SDK 7.1010.2-sidebars.json | 8 + android_versions.json | 1 + 12 files changed, 6217 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.2-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.2/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.2/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.2/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidintegrationguide.md new file mode 100644 index 0000000..f175114 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidintroduction.md new file mode 100644 index 0000000..71f733b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidintroduction.md @@ -0,0 +1,174 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.1-RC.0-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.1** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md new file mode 100644 index 0000000..66f35d5 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md @@ -0,0 +1,451 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md new file mode 100644 index 0000000..a074b1e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md @@ -0,0 +1,2027 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.2-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 7d073a9..47fdc3c 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.2", "Android SDK 7.1010.1", "Android SDK 7.1009.5", "Android SDK 7.1008.6", From 8564592be3f3bf04646a79bb59eb8ac0b027391c Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Wed, 2 Jul 2025 11:34:13 +0200 Subject: [PATCH 104/115] Resolving versions conflict (#138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mering dev to Main (#135) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) --------- * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --------- * Add: Estonian as locale * Add: Preauth for JavaScript SDK * Add: Pre-Auth release notes, Win and JS docs, Postman collection * Update androidreleasenotes.md * Update androidtransactions.md * Update androidtransactions.md * Update javascriptreleasenotes.md * Update androidreleasenotes.md * Update javascriptreleasenotes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowstransactions.md --------- * chore: Increase timeout GHA (#81) chore: Increase Timeout GHA wf deploy * Feature tokenize and modify operation (#84) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md --------- * Fix: Tokenize and modify code sample (#85) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md * Fix: TokenizeAndModify code sample --------- * Add: MoTo PreAuth for Android, JS SDK and REST API (#86) * CICD-55 (#87) chore: use new txn feed doc address * DOCWEB-80 (#88) fix: remove tipAmount for preAuth operations * SDK-3434 (#89) * fix: remove tipAmount parameter from PreAuthorizationCapture * chore: remove typo * fix: include moToPreAuthorization in operation types (possible values) (#90) * REST-API doc fix (#91) chore: add preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal to the operations that require the originalTransactionId parameter * Fixes PreAuth WinSDK (#92) Add: FAILED to GTS finStatus for WinSDK - Add: FAILED to GTS finStatus for WinSDK - Fix: Connect method integration guide for WinSDK - Fix: TipConfiguration code example for REST API * Preauth Rest Api (#93) Add: Card brand tables for PreAuth Capture Add: Card brand tables for PreAuth Capture Add: CAPTURED FinStatus Del: tip amount for PreAuth Increase & Capture * Add: New terminals and features (#94) Add: New terminals and features Fix: PreAuth Capture tables and Reversals info. * Created new SDKs and REST API versions (#95) * Fix: Preauth for all SDKs and REST API * Update androidtransactions.md * Update androidtransactions.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restobjects.md * Update restobjects.md * Update windowstransactions.md * Update windowstransactions.md --------- * Add new terminals, T&M Release notes (#96) * Add: BP50+, more terminals and T&M release Notes * Fix * Update androidreleasenotes.md * Update androidreleasenotes.md * Update cpdocs.js --------- * Add: Money Remittance docs (Android, JS, Win and REST API) (#98) * Add: Money Remittance docs (Android, JS, Win and REST API) * Update androidobjects.md * Update androidreleasenotes.md * Update androidobjects.md * Update androidreleasenotes.md * Update: Android SDK version (7.1004.1) * Update: REST API Postman Collection uodate * Update androidobjects.md * Update javascriptobjects.md * Update javascriptreleasenotes.md * Update restintroduction.md * Update restobjects.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowsobjects.md --------- * Add: New versions (Money Remittance) (#99) * Add mremittance examples (#101) * Add: Money Remittance code examples * Upd: Postman Collection with MRemittance examples * Add automatic refunds (#104) * Added Automatic Refunds Add: Automatic Refunds Fix: Report Configuration * Update Automatic Partial Refund * Update androidtransactions.md --------- * Add release notes 7.1004.2 (#105) * Added Release Notes 7.1004.2 Android SDK * Added Fix Slovenian formatting currency * Add: New version 7.1004.2 Android SDK (#106) * TMS landing page 2024 (Including TMS API docs link) (#108) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Updated Docs Links (#109) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Update docusarus.config links * Changed device name from HiLite Plus to BluePad 50+ (#111) Changed name from HiLite Plus to BluePad 50+ * Add sdk 7.1005.0 (#113) * Add 7.1005.0 SDK * updated admonition * Created version Android SDK 7.1005.0 (#114) Created version 7.1005.0 * Added new code example for USB (#116) * New GTS endpoint added (#117) * Removing HiPro, adding IM25 (#118) * EFTCLIENT-5268 Add tokenization operations in the JS SDK (#119) Adding documentation for JavaScript SDK version 7.2.2 * SDK-3815 (#120) * Add tokenize option in Windows SDK docs TODO: link this to the general description of our tokenize feature when ready, which is under development * Adding description of tokenized payments operations as a feature * Adding Android SDK 7.1009.5 version * Adding tokenized payments operations (standalone) * Adding missing Android SDK versions and adding draft of Tokenized Payments Operations overview TODO: complete 7.1009.4 release notes * Adding tokenized payments operations TODO: review text and format * Fixing some formatting * Linking to detailed information on tokenize in JS and Win SDKs * Integrationg Tokenize and Modify in new Tokenized Payments Operations * Removing PLM info that should not be public * Masking info * REST API and SDK updates (#121) * REST API and SDK updates Updating RestAPI endpoints: Added commands, small fixes Updating SDK versions -> removed maven repository and indicate Nexus for both dev and prod SDK versions. Removed A8900 from release notes. converted mermaid to PNG diagrams due to docusaurus v2.1.0 limitations * corrected links for restobjects.md changed restobjects.md to restobjects, looks like the build test doesn't like it in github although it does run locally * corrected typo on link causing broken link * rolled back acquirer's ENUM (#122) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * removed HiPro reference from iOS SDK (#123) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * Add tokenize parameter (#125) * added tokenize parameter Added tokenize parameter to restAPI documentation in Objects and in release Notes corrected tokenize parameter type in windows SDK * add tokenize parameter REST API: added tokenize parameter to both transaction object and to release notes Windows SDK: corrected the tokenize parameter type from String to Boolean * SDK-3856 iOS SDK 4.0.2 (#129) * feat: included version 4.0.2 * chore: removed unused section * feat: included release notes section for SDK iOS * docs: SDK-3854_1 Update README (#128) * docs: SDK-3854_2 Add info about Docusaurus (#131) * SDK-3887 (#132) feat: Adding Android SDK 7.1010.1 version * SDK-3886 (#133) ➕ A8900 ➕ iOS 4.0.2 ➖ manual 'entry transaction' references under MoTo ➖ HiLite Logs gathering info (not available for Prod devices) * Add a8900 description (#134) Added communications row for A8900 --------- Co-authored-by: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Miguel Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Co-authored-by: Vicente Pavón <30615276+vicentepdj@users.noreply.github.com> Co-authored-by: Raul Carrasco From 23cd4d66773fd59c8a1e7c0d2d43f7b7f4accaf1 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Wed, 23 Jul 2025 11:03:22 +0200 Subject: [PATCH 105/115] SDK-3923 (#140) feat: Adding Android SDK 7.1010.3 version documentation --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 174 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 457 ++++ .../androidtransactions.md | 2027 +++++++++++++++++ ...version-Android SDK 7.1010.3-sidebars.json | 8 + android_versions.json | 1 + 12 files changed, 6223 insertions(+) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.3-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.3/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.3/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.3/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidintegrationguide.md new file mode 100644 index 0000000..f175114 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidintroduction.md new file mode 100644 index 0000000..71f733b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidintroduction.md @@ -0,0 +1,174 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.1-RC.0-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.1** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md new file mode 100644 index 0000000..b054eb3 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md @@ -0,0 +1,457 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +::: + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md new file mode 100644 index 0000000..a074b1e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md @@ -0,0 +1,2027 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.3-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 47fdc3c..098d2e1 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.3", "Android SDK 7.1010.2", "Android SDK 7.1010.1", "Android SDK 7.1009.5", From 3055b042c8bfe67b91b8da4afc31c63061ad2c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Mon, 18 Aug 2025 16:01:52 +0200 Subject: [PATCH 106/115] MISC-751 Remove Google Analytics and HubSpot tracking scripts from documentation sites (#142) * chore(docusaurus): remove Hubspot tracking script * chore(docusaurus): remove GA tracking script --------- Co-authored-by: ecunado --- docusaurus.config.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 36102ac..ed2db3e 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -229,10 +229,6 @@ module.exports = { [ '@docusaurus/preset-classic', { - googleAnalytics: { - trackingID: 'UA-1295190-6', - anonymizeIP: false, - }, docs: { sidebarPath: require.resolve('./sidebars.js'), includeCurrentVersion: true, @@ -253,9 +249,6 @@ module.exports = { ], ], scripts: [ - // String format. - 'https:////js-eu1.hs-scripts.com/25846579.js', - ], plugins: [ // require.resolve('docusaurus-lunr-search', { From ba07d525b1e6c6d09e2644075bac41c28a6aac1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Mon, 18 Aug 2025 22:15:08 +0200 Subject: [PATCH 107/115] MISC-751 Remove subscribe link from newsletter message (#143) * chore(docusaurus): remove Hubspot tracking script * chore(docusaurus): remove GA tracking script * chore: Remove subscribe link from newsletter message --------- Co-authored-by: ecunado --- android/androidreleasenotes.md | 2 +- .../version-Android SDK 6.6.7/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.0/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.2/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.3/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1001.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1002.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.5/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.6/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1009.5/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.3/androidreleasenotes.md | 2 +- ios/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md | 2 +- javascript/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.0.1/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.1.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.2.1/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.3.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.0.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.1.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.2.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.2.2/javascriptreleasenotes.md | 2 +- .../version-Javascript SDK 6.2.0/javascriptreleasenotes.md | 2 +- restapi/restreleasenotes.md | 2 +- .../version-REST API 2.10.0/restreleasenotes.md | 2 +- .../version-REST API 2.12.0/restreleasenotes.md | 2 +- .../version-REST API 2.13.0/restreleasenotes.md | 2 +- .../version-REST API 2.14.0/restreleasenotes.md | 2 +- .../version-REST API 2.15.0/restreleasenotes.md | 2 +- .../version-REST API 2.17.0/restreleasenotes.md | 2 +- .../version-REST API 2.20.0/restreleasenotes.md | 2 +- .../version-REST API 2.6.0/restreleasenotes.md | 2 +- .../version-REST API 2.7.1/restreleasenotes.md | 2 +- windows/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.4/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.5/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.3.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.4.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.0.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.1.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.2.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.3.1/windowsreleasenotes.md | 2 +- 67 files changed, 67 insertions(+), 67 deletions(-) diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index cfc7bf3..6d34628 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.0 diff --git a/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md index 6170de5..c79383a 100644 --- a/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.6.7 diff --git a/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md index 67e9cbc..5032af7 100644 --- a/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.7.0 diff --git a/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md index 3069ecb..05cdd7d 100644 --- a/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.7.2 diff --git a/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md index 815f35a..d20eeb2 100644 --- a/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.7.2 diff --git a/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md index a9fb6a1..51f9f92 100644 --- a/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.7.4 diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md index 2c580dc..6ed4382 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.0.1 diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md index 2972937..b702abf 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.0.1 diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md index 63837ae..53776c9 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md index 9362078..0344a76 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md index 1c8b3d4..e7cb596 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md index 9347a5e..70ad553 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1004.0 diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md index 9e5c2bb..fdd4c5d 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1004.1 diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md index 3fba142..8996c11 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1004.2 diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md index cfc7bf3..4ef9771 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1005.0 diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md index 5ff5102..85bc6f7 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1005.1 diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md index fa68e44..e3b7452 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1005.2 diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md index bd7e148..7682893 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1005.3 diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md index 74a2b1a..afbf4ff 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1005.4 diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md index 50601bd..6569bd9 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1006.0 diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md index 219e0bb..ba46c20 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1006.1 diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md index 84e0d9d..5e12d31 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1006.2 diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md index 8d9b882..93ffeca 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1006.3 diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md index aac119d..6b53756 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.0 diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md index 68cea4a..c0c8228 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.1 diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md index 06b3eff..9ac92b6 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.3 diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md index 174f082..7663902 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.4 diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md index 415e4c0..ef9948c 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.5 diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md index c06a693..d4f9243 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1008.6 diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md index e1e92fd..c737486 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1009.5 diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md index 3a8b62e..51dbf7f 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1010.1 diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md index 66f35d5..c06dc10 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md index b054eb3..119506e 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/ios/iosreleasenotes.md b/ios/iosreleasenotes.md index 3368714..2192361 100644 --- a/ios/iosreleasenotes.md +++ b/ios/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.0.2 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md index e3dff0c..7b655ae 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.0.0 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md index 5ac696c..c6cf136 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.0.1 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md index 3368714..2192361 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.0.2 diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index 7245f13..f1e200f 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.2.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md index 0043ffd..3ccb0d0 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md @@ -8,7 +8,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md index 1e9ba30..b88e4db 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md index f1e51ab..2c78617 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md index f8a2876..cbdc682 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 6.3.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md index a5fc7d3..f0e8fc8 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.0.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md index 992b6d5..56dadd6 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.1.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md index 7245f13..f1e200f 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.2.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md index 9fbb952..9a8551f 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 7.2.2 diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md index 2ba0e6b..c1ab588 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 1224d76..cdd0494 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.17.0 diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md index c657c23..f8acf42 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.10.0 diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md index 58acd2e..8564f9b 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md index 8e24f93..7ff73d8 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.13.0 diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md index 9880b1b..b631761 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.14.0 diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md index 7a45b5b..e6953de 100644 --- a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md index 532b68c..b613e38 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.17.0 diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md index 83cf468..d98365f 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.20.0 diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md index 2cb989c..73081d8 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.6.0 diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md index 7b20aa7..2bae605 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 2.7.1 diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index e3682fc..8aedab2 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md index e97a634..32b03ec 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 3.2.0 diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md index 2ad3a8e..b0edf61 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 3.2.4 diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md index 7a7605b..a5a0c4b 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md index 77c54d5..c9fa2c2 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 3.3.0 diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md index deaa568..d498659 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md index c09f2df..a59fa02 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.0.0 diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md index 0d45728..91eaca0 100644 --- a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.1.0 diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md index b84f0c9..8198cb8 100644 --- a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md index 8352047..52919b5 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Do not miss any news from Handpoint releases. [Subscribe](https://handpoint.us6.list-manage.com/subscribe?u=4d9dff9e7edb7e57a67a7b252&id=0a2179241e) to our Handpoint Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! ::: ## 4.3.1 From bc8a54efd11bda0bff0c7c2944a139a7e15f9620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Cu=C3=B1ado?= Date: Mon, 18 Aug 2025 22:32:59 +0200 Subject: [PATCH 108/115] MISC-751 Remove subscribe link from newsletter message (#145) chore: Remove subscribe link from newsletter message Co-authored-by: ecunado --- .../version-Android SDK 6.6.7/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.0/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.2/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.3/androidreleasenotes.md | 2 +- .../version-Android SDK 6.7.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.0.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1001.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1002.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1004.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1005.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1006.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.0/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.3/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.4/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.5/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1008.6/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1009.5/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.1/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.2/androidreleasenotes.md | 2 +- .../version-Android SDK 7.1010.3/androidreleasenotes.md | 2 +- ios/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md | 2 +- ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md | 2 +- javascript/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.0.1/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.1.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.2.1/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 6.3.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.0.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.1.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.2.0/javascriptreleasenotes.md | 2 +- .../version-JavaScript SDK 7.2.2/javascriptreleasenotes.md | 2 +- .../version-Javascript SDK 6.2.0/javascriptreleasenotes.md | 2 +- restapi/restreleasenotes.md | 2 +- .../version-REST API 2.10.0/restreleasenotes.md | 2 +- .../version-REST API 2.12.0/restreleasenotes.md | 2 +- .../version-REST API 2.13.0/restreleasenotes.md | 2 +- .../version-REST API 2.14.0/restreleasenotes.md | 2 +- .../version-REST API 2.15.0/restreleasenotes.md | 2 +- .../version-REST API 2.17.0/restreleasenotes.md | 2 +- .../version-REST API 2.20.0/restreleasenotes.md | 2 +- .../version-REST API 2.6.0/restreleasenotes.md | 2 +- .../version-REST API 2.7.1/restreleasenotes.md | 2 +- windows/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.4/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.2.5/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.3.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 3.4.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.0.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.1.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.2.0/windowsreleasenotes.md | 2 +- .../version-Windows SDK 4.3.1/windowsreleasenotes.md | 2 +- 66 files changed, 66 insertions(+), 66 deletions(-) diff --git a/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md index c79383a..985c0d4 100644 --- a/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.6.7/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.6.7 diff --git a/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md index 5032af7..2e7e3da 100644 --- a/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.7.0 diff --git a/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md index 05cdd7d..49e6cb2 100644 --- a/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.7.2 diff --git a/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md index d20eeb2..7c7d145 100644 --- a/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.7.2 diff --git a/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md index 51f9f92..85d4357 100644 --- a/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 6.7.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.7.4 diff --git a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md index 6ed4382..0fce27a 100644 --- a/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.0.1 diff --git a/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md index b702abf..89a7ed6 100644 --- a/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.0.1 diff --git a/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md index 53776c9..86b5075 100644 --- a/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.0.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md index 0344a76..a735002 100644 --- a/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1001.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md index e7cb596..f5623a5 100644 --- a/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1002.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md index 70ad553..6504ec9 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1004.0 diff --git a/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md index fdd4c5d..092cbb6 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1004.1 diff --git a/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md index 8996c11..68afd36 100644 --- a/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1004.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1004.2 diff --git a/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md index 4ef9771..6d34628 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.0 diff --git a/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md index 85bc6f7..5f47ae1 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.1 diff --git a/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md index e3b7452..3cf6fe1 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.2 diff --git a/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md index 7682893..ec0b697 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.3 diff --git a/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md index afbf4ff..a7012a3 100644 --- a/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1005.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1005.4 diff --git a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md index 6569bd9..dfb1b26 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1006.0 diff --git a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md index ba46c20..6711976 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1006.1 diff --git a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md index 5e12d31..5984e31 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1006.2 diff --git a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md index 93ffeca..8f4ec8e 100644 --- a/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1006.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1006.3 diff --git a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md index 6b53756..ae09211 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.0/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.0 diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md index c0c8228..5e6e62f 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.1 diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md index 9ac92b6..37bdff5 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.3 diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md index 7663902..a96a018 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.4 diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md index ef9948c..e936371 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.5 diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md index d4f9243..e0bef3b 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1008.6 diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md index c737486..7484d1b 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1009.5 diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md index 51dbf7f..c207f40 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1010.1 diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md index c06dc10..eb4bb8d 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md index 119506e..1076b09 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidreleasenotes.md @@ -8,7 +8,7 @@ id: androidreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/ios/iosreleasenotes.md b/ios/iosreleasenotes.md index 2192361..8a07f74 100644 --- a/ios/iosreleasenotes.md +++ b/ios/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.0.2 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md index 7b655ae..78617da 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.0/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.0.0 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md index c6cf136..c595b19 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.1/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.0.1 diff --git a/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md index 2192361..8a07f74 100644 --- a/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md +++ b/ios_versioned_docs/version-iOS SDK 4.0.2/iosreleasenotes.md @@ -8,7 +8,7 @@ id: iosreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.0.2 diff --git a/javascript/javascriptreleasenotes.md b/javascript/javascriptreleasenotes.md index f1e200f..93db530 100644 --- a/javascript/javascriptreleasenotes.md +++ b/javascript/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.2.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md index 3ccb0d0..0031baa 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.0.1/javascriptreleasenotes.md @@ -8,7 +8,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md index b88e4db..7a64d95 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.1.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md index 2c78617..15011a8 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.2.1/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md index cbdc682..7d657da 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 6.3.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 6.3.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md index f0e8fc8..9fc1345 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.0.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.0.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md index 56dadd6..8ad8e53 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.1.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.1.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md index f1e200f..93db530 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.2.0 diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md index 9a8551f..a45fdff 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 7.2.2 diff --git a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md index c1ab588..fe55a64 100644 --- a/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-Javascript SDK 6.2.0/javascriptreleasenotes.md @@ -6,7 +6,7 @@ id: javascriptreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index cdd0494..89b170a 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.17.0 diff --git a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md index f8acf42..ab41277 100644 --- a/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.10.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.10.0 diff --git a/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md index 8564f9b..1eeab45 100644 --- a/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.12.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md index 7ff73d8..75a7656 100644 --- a/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.13.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.13.0 diff --git a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md index b631761..cd9971b 100644 --- a/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.14.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.14.0 diff --git a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md index e6953de..6969b42 100644 --- a/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.15.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md index b613e38..23d381a 100644 --- a/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.17.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.17.0 diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md index d98365f..20f0be3 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.20.0 diff --git a/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md index 73081d8..619694d 100644 --- a/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.6.0/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.6.0 diff --git a/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md index 2bae605..c0d23bb 100644 --- a/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.7.1/restreleasenotes.md @@ -6,7 +6,7 @@ id: restreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 2.7.1 diff --git a/windows/windowsreleasenotes.md b/windows/windowsreleasenotes.md index 8aedab2..f29447f 100644 --- a/windows/windowsreleasenotes.md +++ b/windows/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md index 32b03ec..a497414 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 3.2.0 diff --git a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md index b0edf61..632160e 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.4/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 3.2.4 diff --git a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md index a5a0c4b..6a1342c 100644 --- a/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.2.5/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md index c9fa2c2..e73b432 100644 --- a/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.3.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 3.3.0 diff --git a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md index d498659..71ce608 100644 --- a/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 3.4.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md index a59fa02..66e480d 100644 --- a/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.0.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.0.0 diff --git a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md index 91eaca0..a3156ca 100644 --- a/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.1.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.1.0 diff --git a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md index 8198cb8..82e6058 100644 --- a/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.2.0/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md index 52919b5..4b67eae 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md @@ -6,7 +6,7 @@ id: windowsreleasenotes # Release Notes :::tip -Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter!Newsletter! +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: ## 4.3.1 From c1c765eb6f187ee6fca3f430f7f3ba0ed3d4e254 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Mon, 15 Sep 2025 18:37:30 +0200 Subject: [PATCH 109/115] DOCWEB-84 (#146) * feat: Adding base files for new versions docs Android SDK 7.1010.5, REST API 2.22.2, Javascript SDK 7.2.3, Windows SDK 4.4.0. * feat: cardPresent flag added in JS and Android SDKs TODO: add a link to our public confluence page where this will be detailed * Android SDK 7.1010.5 release notes upgraded * Upgrading Android SDK release notes * Adding cardPresent parameter in Windows SDK docs and fixing broken links * Adding cardPresent flag in REST API docs * Providing an actual link for further info instead of the temporary "TODO" --- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 832 +++++++ .../androidintroduction.md | 174 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 463 ++++ .../androidtransactions.md | 2027 +++++++++++++++++ ...version-Android SDK 7.1010.5-sidebars.json | 8 + android_versions.json | 1 + .../javascriptobjects.md | 4 +- .../javascriptreleasenotes.md | 2 +- .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 823 +++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 99 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 262 +++ .../javascripttransactiontypes.md | 779 +++++++ ...version-JavaScript SDK 7.2.3-sidebars.json | 8 + javascript_versions.json | 1 + .../version-REST API 2.20.0/restobjects.md | 2 +- .../restreleasenotes.md | 2 +- .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.22.2/restdownloads.md | 10 + .../version-REST API 2.22.2/restendpoints.md | 746 ++++++ .../restintroduction.md | 55 + .../version-REST API 2.22.2/restobjects.md | 825 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 107 + .../version-REST API 2.22.2/restsandbox.md | 44 + .../version-REST API 2.22.2-sidebars.json | 8 + restapi_versions.json | 1 + .../windowsobjects.md | 2 +- .../windowsreleasenotes.md | 2 +- .../windowsapioverview.md | 22 + .../windowsdevicemanagement.md | 361 +++ .../windowsevents.md | 238 ++ .../windowseventsubscribers.md | 73 + .../windowsintegrationguide.md | 2002 ++++++++++++++++ .../windowsintroduction.md | 51 + .../windowsobjects.md | 619 +++++ .../windowsreleasenotes.md | 114 + .../windowstransactions.md | 938 ++++++++ .../version-Windows SDK 4.4.0-sidebars.json | 8 + windows_versions.json | 1 + 49 files changed, 14672 insertions(+), 7 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.5-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.2.3-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.2/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.22.2-sidebars.json create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsapioverview.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsdevicemanagement.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsevents.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowseventsubscribers.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsintegrationguide.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsintroduction.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsobjects.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowsreleasenotes.md create mode 100644 windows_versioned_docs/version-Windows SDK 4.4.0/windowstransactions.md create mode 100644 windows_versioned_sidebars/version-Windows SDK 4.4.0-sidebars.json diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.5/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.5/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.5/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md new file mode 100644 index 0000000..f175114 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md @@ -0,0 +1,832 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. +- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. +- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +**Maven Settings** + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md new file mode 100644 index 0000000..71f733b --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md @@ -0,0 +1,174 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.1-RC.0-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.1** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +#### For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +### Maven Settings + +For production terminals: + +```xml + + com.handpoint.api + sdk + [7.1001.0,) + aar + +``` +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidreleasenotes.md new file mode 100644 index 0000000..8c375f5 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidreleasenotes.md @@ -0,0 +1,463 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + + +## 7.1010.5 +**Features**: + +A new `cardPresent` flag is supported in Integrated mode, which comes from our [REST API](/restapi/restintroduction) or its related Cloud clients [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). This new flag allows to indicate the payments flow that a Reversal operation will imply an actual present card. Please see [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for further information on the purpose of this flag. + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md new file mode 100644 index 0000000..a074b1e --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md @@ -0,0 +1,2027 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.5-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.5-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.5-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 098d2e1..761c2af 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.5", "Android SDK 7.1010.3", "Android SDK 7.1010.2", "Android SDK 7.1010.1", diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md index 58bed4b..41603b5 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptobjects.md @@ -399,7 +399,7 @@ An object to store the customization options for a refund. This object can be em | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| | `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| @@ -461,7 +461,7 @@ An object to store the customization options for a sale operation. This object c | Property | Description | | ----------- | ----------- | | `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| -| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| | `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| | `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| | `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md index a45fdff..d79c048 100644 --- a/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.2/javascriptreleasenotes.md @@ -12,7 +12,7 @@ Don’t miss any updates on our latest releases. Contact your Handpoint relation ## 7.2.2 **Features:** -A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. +A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 7.2.0 **Features:** diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptintroduction.md new file mode 100644 index 0000000..baa4147 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptobjects.md new file mode 100644 index 0000000..2f6b120 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptobjects.md @@ -0,0 +1,823 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient.(**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Reversal Options{#40} + +`ReversalOptions` Object + +An object to store the customization options for a reversal. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptquickintegration.md new file mode 100644 index 0000000..f5c935d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptreleasenotes.md new file mode 100644 index 0000000..595b4d1 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptreleasenotes.md @@ -0,0 +1,99 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 7.2.3 +**Features:** + +A new `cardPresent` parameter is available under [ReversalOptions](javascriptobjects.md#40). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 7.2.2 +**Features:** + +A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 7.2.0 +**Features:** + +We're excited to announce the latest update to our JavaScript SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](javascriptobjects.md#money-remittance-options)), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptterminalmanagement.md new file mode 100644 index 0000000..8bdae19 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascriptterminalmanagement.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascripttransactiontypes.md new file mode 100644 index 0000000..7c2d213 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.3/javascripttransactiontypes.md @@ -0,0 +1,779 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale ([Tip Configuration](javascriptobjects.md#39), [Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + }, + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale and tokenize ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `reversalOptions`
[*ReversalOptions*](javascriptobjects.md#40) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `reversalOptions`
[*ReversalOptions*](javascriptobjects.md#40) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a MOTO sale (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.2.3-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 04d3f90..3c4fb77 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.2.3", "JavaScript SDK 7.2.2", "JavaScript SDK 7.2.0", "JavaScript SDK 7.1.0", diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md index c31f099..798a41e 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restobjects.md @@ -569,7 +569,7 @@ An object to store information about the request sent to the payment terminal. | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| | `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | -| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| **Code example** diff --git a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md index 20f0be3..391d376 100644 --- a/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md +++ b/restapi_versioned_docs/version-REST API 2.20.0/restreleasenotes.md @@ -16,7 +16,7 @@ Added a selector to the [{transactionReference}/status](restendpoints.md#transac Added "commands" to allow greater device control options -A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 2.17.0 **Features:** diff --git a/restapi_versioned_docs/version-REST API 2.22.2/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.22.2/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restdownloads.md b/restapi_versioned_docs/version-REST API 2.22.2/restdownloads.md new file mode 100644 index 0000000..653b02c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restendpoints.md b/restapi_versioned_docs/version-REST API 2.22.2/restendpoints.md new file mode 100644 index 0000000..163cdf3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restendpoints.md @@ -0,0 +1,746 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", + "terminal_type": "PAXA920" + } + ] +``` + +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + + +:::caution +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restintroduction.md b/restapi_versioned_docs/version-REST API 2.22.2/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restobjects.md b/restapi_versioned_docs/version-REST API 2.22.2/restobjects.md new file mode 100644 index 0000000..8579f4b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restobjects.md @@ -0,0 +1,825 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.22.2/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.22.2/restreleasenotes.md new file mode 100644 index 0000000..dd25f6b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restreleasenotes.md @@ -0,0 +1,107 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.22.2/restsandbox.md b/restapi_versioned_docs/version-REST API 2.22.2/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.2/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.22.2-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.22.2-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.22.2-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 430ff18..c38a928 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.22.2", "REST API 2.20.0", "REST API 2.17.0", "REST API 2.15.0", diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md index f4e3ed2..3597a1a 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsobjects.md @@ -351,7 +351,7 @@ A class containing optional transaction parameters now supported by the device. | ----------- | ----------- | |`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| |`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| -|`tokenize`
*Boolean*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +|`tokenize`
*Boolean*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| |`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| | `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| diff --git a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md index 4b67eae..1d6dfcc 100644 --- a/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md +++ b/windows_versioned_docs/version-Windows SDK 4.3.1/windowsreleasenotes.md @@ -11,7 +11,7 @@ Don’t miss any updates on our latest releases. Contact your Handpoint relation ## 4.3.1 **Features:** -A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md). See [Android SDK 7.1009.5](/android/androidreleasenotes#7.1009.5) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. +A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. ## 4.2.0 **Features:** diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsapioverview.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsapioverview.md new file mode 100644 index 0000000..6283367 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: windowsapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsdevicemanagement.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsdevicemanagement.md new file mode 100644 index 0000000..99af86d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsdevicemanagement.md @@ -0,0 +1,361 @@ +--- +sidebar_position: 6 +id: windowsdevicemanagement +--- + +# Terminal Management + +## Connect + +`Connect` Method + +Configures the device as the preferred device and tries to connect to it. Everytime a new connection is started the SDK will make 3 attempts to re-establish the connection. If those attempts fail, the connection is considered dead. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used.| + + +**Code example** + +```csharp +//Connect to a CLOUD device (PAX/Telpo) +Device device = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.Cloud); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +api.Connect(device); + +//Connect to a BLUETOOTH device (HiLite) +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +api.Connect(device); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + + +## Disconnect + +`Disconnect` Method + +Disconnect will stop the active connection (and reconnection process). Please note that the method does NOT ignore the current state of the payment terminal. This means that if a disconnect is attempted during a transaction it will not be successful and the method will return `false`. If a transaction is not in progress, the disconnect will take 1-3 seconds to successfully finish and will then return `true`. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Disconnect from current device +api.Disconnect(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Each time the card reader state changes (ex : going from Connected to Disconnected) the **[*ConnectionStatusChanged*](windowsevents.md#7)** event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was succesful| + +## Set shared secret + +`SetSharedSecret` Method + +Validates your application for this session, thus enabling financial transactions. + +#### Parameters +| Parameter | Notes | +| ----------- | ----------- | +| `sharedSecret` Required
*String* | The shared secret is a an authentication key provided by Handpoint, it is unique per merchant (not per terminal).| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the shared secret +api.SetSharedSecret("0102030405060708091011121314151617181920212223242526272829303132"); +``` + +#### Events invoked + +**None** + +No events invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + + +## Set logging level + +`SetLogLevel` Method + +Sets the log level (info, debug etc.) for both the payment terminal and the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](windowsobjects.md#9) | The desired log level. Possible values are `LogLevel.None`, `LogLevel.Info`, `LogLevel.Full`, `LogLevel.Debug`.| +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Sets the log level to info +api.SetLogLevel(LogLevel.info); +``` + +#### Events invoked + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request device logs + +`GetDeviceLogs` Method + +Fetches the logs from the payment terminal and reports them to the [DeviceLogsReady](windowsevents.md#WinDeviceLogsReady) event. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Downloads logs from device +api.GetDeviceLogs(); +``` + +#### Events invoked + +**[*DeviceLogsReady*](windowsevents.md#WinDeviceLogsReady)** + +Invoked when the SDK has finished downloading logs from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Request pending transaction results + +`GetPendingTransaction` Method + +In the case of a communication failure between the device and the SDK a TransactionResult might have not been delivered to the API. This function fetches a pending TransactionResult (which contains receipts) from the payment terminal, if any. If no TransactionResult was pending a result will be delivered containing default fields. In order to receive only valid TransactionResults this function should only be called when PendingTransactionResult event is invoked or when HapiManager.IsTransactionResultPending() is true. To receive events when a TransactionResult is pending on the device please add the Events.PendingResults listener. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Fetches a pending TransactionResult from a device +api.GetPendingTransaction(); +``` + +#### Events invoked + +**[*TransactionResultReady*](windowsevents.md#11)** + +Invoked when the SDK has finished fetching a TransactionResult from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## Update device + +`Update` Method + +The update operation checks for available software or configuration update. If an update is pending it will be downloaded and installed by the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | This parameter specifies to the sdk which payment terminal should be used. If none is supplied the system will attempt to use a default device, if any.| + +**Code example** + +```csharp +//Check for card reader update +api.Update(); +``` + +#### Events invoked + +**None** + +Information about this process should be available at the device's screen. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to the payment terminal.| + + +## List Devices (search) + +`ListDevices` Method + +Starts the search for payment terminals to connect to. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](windowsobjects.md#12) | The connection type to the payment terminal (Bluetooth or Cloud)| + +**Code example** + +```csharp +//Search for Bluetooth devices +api.ListDevices(ConnectionMethod.BLUETOOTH); + +//Search for Cloud devices +api.ListDevices(ConnectionMethod.CLOUD); +``` + +#### Events invoked + +**[*deviceDiscoveryFinished*](windowsevents.md#13)** + +Returns a list of available payment terminals. + +## Start monitoring connections + +`StartMonitoringConnections` Method + +Starts a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + + + +## Stop monitoring connections + +`StopMonitoringConnections` Method + +Stops a connection monitoring service. The service listens to events sent by the operating system about the connected hardware. If the service notices that a previously connected device suddenly disconnects on the hardware layer it attempts to reconnect to that particular device. Since this is a service it is necessary that the service is turned off before the application ends its life-time. This means that, if the service was running, stopMonitoringConnections() has to be called before the application is exited completely. Note that the service currently only works with USB. In the case of USB the service will only disconnect from the device and when it notices that it has been plugged in again it will connect to it. + +**Code example** + +```csharp +//Starts the connection monitoring service +//app starts it's life-time +api.StartMonitoringConnections(); +... +//app ends its life-time +api.StopMonitoringConnections(); +``` + +#### Events invoked + +**[*ConnectionStatusChanged*](windowsevents.md#7)** + +Invoked when the status of the connection with the payment terminal changes. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **None**| No information is returned.| + +## Get Transaction Status + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](windowsobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](windowsobjects.md#25) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. +- FAILED - Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to FAILED. This means the operation was unsuccessful and the transaction has not been charged. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [OperationStartResult](windowsobjects.md#OperationStartResult) object.| + +**Code example** + +```csharp +//Gets the current status of a transaction +this.Hapi.GetTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [TransactionResult](windowsobjects.md#14)| An object holding information about the result of a transaction.| \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsevents.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsevents.md new file mode 100644 index 0000000..8d62ada --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsevents.md @@ -0,0 +1,238 @@ +--- +sidebar_position: 8 +id: windowsevents +--- + +# Events Listeners + +## Transaction Result Recovery over CLOUD connection + +`CloudTransactionResultRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [Transaction Result](windowsobjects.md#14) to the point of sale in case it becomes unreachable (network issue or other). +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). +The recovery loop is reinitialized every time the Handpoint application is restarted.The [Transaction Result](windowsobjects.md#14) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The point of sale must be successfully connected to a terminal in order to receive the pending transactions.** + +**Returns:** + +**[*Transaction Result Ready Event*](windowsevents.md#11)** + +Event containing the pending [Transaction Result](windowsobjects.md#14). + +## Device discovery finished{#13} + +`deviceDiscoveryFinished` + +The deviceDiscoveryFinished event gets called when the payment terminal search has finished, it returns a list of devices. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a list of connectable devices +List myListOfDevices = new List(); +public void deviceDiscoveryFinished(List devices) +{ + foreach(Device device in devices) + { + myListOfDevices.Add(device); + } +} +``` + + +## Signature required{#5} + +`SignatureRequired` Method + +The SignatureRequired event gets called when the card issuer requires a signature. This event is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the payment terminal. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](windowsobjects.md#17) | Holds the signature request object.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //You might want to print out the receipt or ask the customer to sign the receipt on your device + DisplayReceiptInUI(signatureRequest.MerchantReceipt) + //If you accept the signature + api.SignatureResult(true); +} +``` + +## End of transaction{#6} + +`EndOfTransaction` Method + +The EndOfTransaction event gets called at the end of each transaction and has two parameters, result and device. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the result and receipts for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a TransactionResult from the SDK. +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + //You might want to display this information in the UI + postTransactionResultToUI(transactionResult); +} +``` + +## Connection status changed{#7} + +`ConnectionStatusChanged` + +The ConnectionStatusChanged event gets called when the state of a payment terminal connection changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](windowsobjects.md#18) | An enum containing the status code for the connection.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a new ConnectionStatus from the SDK +public void ConnectionStatusChanged(ConnectionStatus connectionStatus, Device device) +{ + //You might want to display this information in the UI + postNewStatusToUI(connectionStatus); +} +``` + +## Current transaction status{#4} + +`CurrentTransactionStatus` Method + +The currentTransactionStatus event gets called when the state of an ongoing transaction changes. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `statusInfo` Required
[*StatusInfo*](windowsobjects.md#statusInfo) | An object containing information about the current transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a transaction status from the SDK. +public void currentTransactionStatus(StatusInfo statusInfo, Device device) +{ + //You might want to display some of this information in the UI + DisplayTransactionStatusInUI(statusInfo) +} +``` + +## Message logged + +`OnMessageLogged` Method + +The OnMessageLogged event gets called for each and every message logged by the SDK. This function is only intended for debugging. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logLevel` Required
[*LogLevel*](windowsobjects.md#9) | An enum containing the log level.| +| `message` Required
*String* | A String containing the current log message.| + +**Code example** + +```csharp +//Receiving a log from the SDK +public void OnMessageLogged(LogLevel logLevel, String message) +{ + //You do not want to display this information in the UI + Debug.WriteLine(message); +} +``` + +## Device Logs ready{#WinDeviceLogsReady} + +`DeviceLogsReady` Method + +The DeviceLogsReady event gets called when the payment terminal logs are ready to be delivered (in response to a request to getDeviceLogs()). This Event is useful if case of a communication error between the payment terminal and the API (e.g : Bluetooth communication lost). After reconnecting, you can then fetch the card reader logs to the API. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `logs` Required
*String* | String containing the current log.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +//Receiving a log from the device +public void DeviceLogsReady(string logs, Device device) +{ + //You might want to save this information + WriteLogsToDisk(logs); +} +``` + +## Pending transaction result + +`PendingTransactionResult` Method + +In case of a communication failure between the payment terminal and your application a TransactionResult might have not been delivered to the SDK. This event is invoked when the device has a pending TransactionResult. This event might be invoked when reconnecting to a device after a communication failure during a transaction. This event will not be called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void PendingTransactionResult(Device device){ + //Here you might want to call api.GetPendingTransaction(); to receive the TransactionResult +} +``` + +## Transaction result ready{#11} + +`TransactionResultReady` Method + +In case of a communication failure between the device and your application a TransactionResult might have not been delivered to the SDK. This event will be invoked after using hapi.GetPendingTransaction();. When there is no pending transaction the TransactionResult will contain default/error fields and no receipts. This event is called if HapiManager.Settings.AutoRecoverTransactionResult is set to true. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](windowsobjects.md#14) | Holds the results for the transaction.| +| `device` Required
[*Device*](windowsobjects.md#2) | The payment terminal invoking the event.| + +**Code example** + +```csharp +@Override +public void TransactionResultReady(TransactionResult transactionResult, Device device){ + //Here you might want to do stuff to the transactionResult +} +``` diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowseventsubscribers.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowseventsubscribers.md new file mode 100644 index 0000000..4f361cf --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowseventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: windowseventssubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`RegisterEventsDelegate` Method + +Registers a delegate for the SDK events. The method getAsyncInterface in HapiFactory executes internally this subscription. + +##### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void RegisterEventHandler() { + // Register this class as listener for events + this.api.RegisterEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`UnregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any Object implementing one or more of the available delegate interfaces| + +**Code example** + +```csharp +public class ObjectHelper : Events.Required, Events.Status, Events.Log { + ... + private void Unsubscribe() { + // Stop receiving events + this.api.UnregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removedded successfully.| + + diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintegrationguide.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintegrationguide.md new file mode 100644 index 0000000..1ff930d --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintegrationguide.md @@ -0,0 +1,2002 @@ +--- +sidebar_position: 4 +id: windowsintegrationguide +--- + +# Integration Guides + +**The SDK supports the following connection methods:** + +1. **[Cloud (PAX/Telpo)](#WinPaxIntegration)** +2. **[Bluetooth (HiLite)](#WinHiLiteIntegration)** + +## Cloud (PAX/Telpo) {#WinPaxIntegration} + +### Introduction + +### Let's start programming! + +**1. Create a C# class** + +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} +``` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is a free field. + // The Api key is a unique key per merchant used to authenticate the terminal against the Cloud. + // You should replace the API key with the one sent by the Handpoint support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // here you get a list of payment terminals associated with the api key. + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + // Ignore for a PAX/Telpo integration. The complete signature capture process + // is already handled in the sdk, a dialog will prompt the user for a signature if required. + // If a signature was entered, it should be printed on the receipts. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to list the terminals of your merchant and connect to one of them** +Ensure that the card reader and PC are correctly paired via Cloud connection. + +```csharp +public void DiscoverDevices() +{ + // This triggers the search for all the cloud devices related to your Api Key. + api.SearchDevices(ConnectionMethod.CLOUD); +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + // Put the name of your device + + { + this.myDevice = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.myDevice); + //Connection to the device is handled automatically by the api + } + } + } +} +``` + +**5. Add a method to connect directly to the payment terminal** +Instead of discovering terminals you can also connect directly to one of them: + +```csharp +public void DirectConnect() +{ + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + // new Device("name", "address", "port (optional)", ConnectionMethod); + // The address always has to be written in UPPER CASE + // It is the composition of the serial number and model ot the payment terminal. + // Example for a PAX A920 device: serial_number - model -> 0821032395-PAXA920 + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public OperationStartResult Pay() +{ + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency +} +``` + +**7. Add a method to get the transactions status** + +This functionality is only available for SmartPos devices (PAX). + +```csharp +public TransactionResult GetTransactionStatus(String transactionReference) +{ + return api.GetTransactionStatus(transactionReference); +} +``` + +**8. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**9. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032395-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + return api.Sale(new BigInteger(1000), Currency.EUR); + // Let´s start our first transaction for 10 euros + // The amount should always be in the minor unit of the currency + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons and labels** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 4 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "GetTransactionStatusButton" +- Change the attribute "text" from "button2" to "Get Transaction Status" +- Change the attribute "Name" from "button3" to "ConnectButton" +- Change the attribute "text" from "button3" to "Connect To Card reader" +- Change the attribute "Name" from "button4" to "DisconnectButton" +- Change the attribute "text" from "button4" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Do the same with the button "Get Transaction Status". Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**1. Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} +``` + +**2. Create the UpdateLabel method in Form1.cs** + +```csharp +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in Form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like: + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-is-my-api-key-provided-by-Handpoint" + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.CLOUD); + } + + public void DirectConnect() + { + Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); + api.Connect(device); + } + + public OperationStartResult Pay() + { + //A new sale operation will generate a transactionReference that can be used + //to check the status of the transaction (GetTransactionStatus) + return api.Sale(new BigInteger(1000), Currency.EUR); + } + + public TransactionResult GetTransactionStatus(String transactionReference) + { + return api.GetTransactionStatus(transactionReference); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("***ConnectionStatus*** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("CloudDevice")) + { + this.myDevice = device; + api.Connect(this.myDevice); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + + public void SignatureRequired(SignatureRequest request, Device device) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Drawing; + using System.Windows.Forms; + + namespace GettingStartedApp + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } + } +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers. +5. Click "Get Transaction Status", you will get the transaction Status from the used transactionReference +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Bluetooth (HiLite) {#WinHiLiteIntegration} + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows devices integrated with an HiLite terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### How to implement a Sale Transaction + +The below flow chart shows the interaction between the SDK, the payment terminal and your application. The orange arrows represent methods (requests) that need to be invoked to communicate with the Handpoint SDK's. The dark arrows represent events that need to be integrated in your code in order to retrieve information from the SDK´s and the card reader. + +![Sandbox logo](/img/SaleTransaction.png) + +### How to implement a Sale Transaction with Recovery feature + +At some point, the connection between the SDK and the card reader can become unstable. For example, the Bluetooth connection can be cut in the middle of a sale transaction if the smartphone runs out of battery. If this happens, you need to have implemented the “transaction recovery feature” in order to get the receipts from the previous transaction and knowing if it was successful despite the connection problem. + +![Sandbox logo](/img/SaleTransactionRecovery.png) + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + } +} + +```` + +**2. Initialize the API** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + // You should replace this default shared secret by the one sent by our support team. + } + } +} +``` + +**3. Implement the mandatory Events(Events.Required) and per recommendation Status events (Events.Status)** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DeviceDiscoveryFinished(List devices) + { + // Here you get a list of Bluetooth payment terminals paired with your computer + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The TransactionResult object holds details about the transaction as well as the receipts. + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + // The ConnectionStatus object holds details about the status regarding the connection to the target device. + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + // The StatusInfo object holds details about the status and step taken during the transaction. + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + // Ignore, legacy event, will be deleted in future version. + } + } +} +``` + +**4. Add a method to discover surrounding devices and connect to the card reader** +Ensure that the card reader and PC are correctly paired via bluetooth. + +```csharp +public void DiscoverDevices() +{ + api.ListDevices(ConnectionMethod.BLUETOOTH); + // This triggers the search for all the bluetooth devices around. + // You can also search for USB and Serial as a connection method +} + +public void DeviceDiscoveryFinished(List devices) +{ + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + // Put the name of your device, find it by doing C then up arrow on your card reader keypad + { + this.device = device; + //We'll remember the device for this session, it is nice if you would do that too + api.Connect(this.device); + //Connection to the device is handled automatically in the API + } + } + } +} +``` +**5. Add a method to connect directly to the card reader** +Instead of discovering the surrounding devices you can also directly connect to the card reader by implementing the following method: + +```csharp +public void DirectConnect() +{ + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //new Device("name", "address", "port", ConnectionMethod); + //The address always has to be written in UPPER CASE + api.Connect(device); +} +``` + +**6. Add a method to take payments** + +```csharp +public bool Pay() +{ + return api.Sale(new BigInteger(1000), Currency.GBP); + // Let´s start our first payment of 10 pounds +} +``` + +**7. Add a method to disconnect from the card reader** + +```csharp +public void Disconnect() +{ + api.Disconnect(); +} +``` + +**8. Eventually, MyClass.cs must look like this after implementing all the necessary methods :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + + public MyClass(Form1 form1) + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GPB); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +### Let's create a User Interface! + +**1. Create buttons** +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 3 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "PayButton" +- Change the attribute "text" from "button1" to "Pay Now" +- Change the attribute "Name" from "button2" to "ConnectButton" +- Change the attribute "text" from "button2" to "Connect To Card reader" +- Change the attribute "Name" from "button3" to "DisconnectButton" +- Change the attribute "text" from "button3" to "Disconnect From Card Reader" +- Select View > Toolbox > Common Controls > Label +- Change the attribute "Name" from "label1" to "ConnectionLabel" +- Change the attribute "text" from "label1" to "Disconnected" +- Change the attribute "backColor" from "label1" to "Red" + +**2. Create WebBrowsers** + +Now that we have our 3 buttons, let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label2" to "MerchantReceiptLabel" +- Change the attribute "text" from "label2" to "Merchant Receipt :" +- Change the attribute "Name" from "label3" to "CardholderReceiptLabel" +- Change the attribute "text" from "label3" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp +class MyClass : Events.Required, Events.Status +{ + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + [...] +} +``` + +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Pay Now". By Double Clicking on it you created a method called PayButton_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method PayButton_Click call the Pay() method from MyClass. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + private void GetTransactionStatusButton_Click(object sender, EventArgs e) + { + //Use a transactionReference from your own transactions. 91ff1ed2-beee-44ca-96f9-9acec74dc659 is a test transactionReference + my.GetTransactionStatus("91ff1ed2-beee-44ca-96f9-9acec74dc659"); + } + } +} +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + //my.DiscoverDevices(); + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + } +} +``` + +### Let´s notify the user when the app is connected and ready to send the transaction + +**Update the ConnectionLabel to notify the user of the connection status** +Get the connection status from the method **[*ConnectionStatusChanged*](#7)** in MyClass.cs. + +```csharp +public void ConnectionStatusChanged(ConnectionStatus status, Device device) +{ + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } +} + +public void CurrentTransactionStatus(StatusInfo info, Device device) +{ + //Let also console log the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); +} + +Create the UpdateLabel method in Form1.cs + +public delegate void UpdateConnectionLabel(bool Connected); +public void UpdateLabel(bool Connected) +{ + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } +} +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp +public void EndOfTransaction(TransactionResult transactionResult, Device device) +{ + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); +} +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp +public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); +public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) +{ + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } +} +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp +using System; +using System.Collections.Generic; +using System.Numerics; +using com.handpoint.api; + +namespace GettingStartedApp +{ + class MyClass : Events.Required, Events.Status + { + Hapi api; + Device myDevice; + private Form1 uIClass; + + public MyClass(Form1 form1) + { + uIClass = form1; + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + } + + public void DiscoverDevices() + { + api.SearchDevices(ConnectionMethod.BLUETOOTH); + } + + public void DirectConnect() + { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + api.Connect(device); + } + + public bool Pay() + { + return api.Sale(new BigInteger(1000), Currency.GBP); + } + + public void Disconnect() + { + api.Disconnect(); + } + + public void ConnectionStatusChanged(ConnectionStatus status, Device device) + { + Console.WriteLine("*** ConnectionStatus *** " + status); + if (status == ConnectionStatus.Connected) + { + uIClass.UpdateLabel(true); + } + else + { + uIClass.UpdateLabel(false); + } + } + + public void CurrentTransactionStatus(StatusInfo info, Device device) + { + //Let's log also the status during the transaction + Console.WriteLine("*** CurrentTransactionStatus *** " + info.Status.ToString()); + } + public void DeviceDiscoveryFinished(List devices) + { + foreach (Device device in devices) + { + if (device.Name != null) + { + if (device.Name.Equals("PP0513901435")) + { + this.device = device; + api.Connect(this.device); + } + } + } + } + + public void EndOfTransaction(TransactionResult result, Device device) + { + Console.WriteLine("*** EndOfTransaction *** " + result.ToJSON()); + uIClass.DisplayReceipts(result.MerchantReceipt, result.CustomerReceipt); + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + } + + public void HardwareStatusChanged(HardwareStatus status, ConnectionMethod hardware) + { + //Ignore + } + } +} +``` + +**2. Form1.cs :** + +```csharp +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace GettingStartedApp +{ + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + + private void PayButton_Click(object sender, EventArgs e) + { + my.Pay(); + } + + private void ConnectButton_Click(object sender, EventArgs e) + { + my.DirectConnect(); + } + + private void DisconnectButton_Click(object sender, EventArgs e) + { + my.Disconnect(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + + public delegate void UpdateConnectionLabel(bool connected); + + public void UpdateLabel(bool Connected) + { + //Only need to check for one of the webbrowsers + if (ConnectionLabel.InvokeRequired) + { + UpdateConnectionLabel d = new UpdateConnectionLabel(UpdateLabel); + this.Invoke(d, new object[] { Connected }); + } + else + { + if (Connected) + { + ConnectionLabel.Text = "Connected"; + ConnectionLabel.BackColor = Color.Green; + } + else { + ConnectionLabel.Text = "Disconnected"; + ConnectionLabel.BackColor = Color.Red; + } + } + } + + } +} +``` + +### Let's run our program! + +Run the program by clicking the "play" button : + +1. Click on "Connect To Card Reader", this can take a little bit of time (10 sec max) due to the fact that we are looking for all the devices around before connecting to a specific one +2. Click "Pay Now" +3. Follow the instructions on the card reader +4. When the transaction is finished, the receipts should be displayed in the webBrowsers +5. Click on "Disconnect From Card Reader" to stop the connection with the card reader + +## Terminal Simulator Integration + +### Introduction + +This tutorial is guiding you through all the steps to create a basic payment application for Windows using a card reader simulator. The simulator only has limited capabilities and we highly recommend that you order a development kit if you want to carry a full integration. The development kit contains a card reader as well as a test card and will allow you to test your integration from end to end. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +### Connecting to the simulator + +The SDK offers a method in which you will need to specify the card reader to be used: + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.****)) +``` + +Simply set the ConnectionMethod to Simulator, i.e. ConnectionMethod.Simulator. The SDK does the rest. You don't need to search via bluetooth for surrounding card readers when using the simulator. + +```csharp +hapi.Connect(new Device("Name", "Port", "Address", ConnectionMethod.Simulator)) +``` + +### Controlling responses + +The simulator mimics the card reader as much as possible regarding information flow from the SDK interface to your application. It will return all the transaction statuses, transaction results and receipts. + +Results of a transaction are controlled by the amount sent into the sale function:
+The 3rd position from the right sets the desired financial status, 0 = Authorized and 1 = Declined.
+The 4th position from the right sets the desired verification method, 0 = Signature and 1 = PIN. + +```csharp +hapi.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +- X 00 XX = Signature authorized +- X 01 XX = Signature declined +- X 10 XX = Pin authorized +- X 11 XX = Pin declined + +### Let's start programming! + +**1. Create a C# class** +Create a new C# class called MyClass and include com.handpoint.api as a dependency : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + } + } +``` + +**2. Initialize the API** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass + { + Hapi api; + + public MyClass() + { + InitApi(); + } + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + } + } +``` + +**3. Implement the mandatory Events(Events.Required)** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult holds the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +**4. Add a method to connect to the simulator** + +```csharp + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } +``` + +**5. Add a method to take payments with the simulator** + +The simulator mimics the card reader as much as possible regarding the information flow from the SDK interface to your application. The results of the transaction (declined, authorized) and the type of verification method (PIN, signature) will depend on the amount used. + +You can get different responses from the simulator by setting different values for the amount parameter, e.g. for a Sale function : + +```csharp + api.Sale(X10XX, Currency.GBP); // amount = X 10 XX - where X represents an integer [0;9] +``` + +**Amount Values** + +- X00XX = Signature authorized +- X01XX = Signature declined +- X10XX = PIN authorized +- X11XX = PIN declined + +The 3rd number from right sets desired financial status, Authorized or Declined. Default status is Authorized.
+The 4th number from right sets desired verification method, Signature or PIN. Default method is Signature. + +Let´s add 4 methods to MyClass in order to represent the 4 cases above : + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + + public MyClass() + { + InitApi(); + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + } + } +``` + +### Let's create a User Interface! + +**1. Create buttons** + +- Go to your user interface (usually Form1.cs[Design]) +- Select View > Toolbox +- In the toolbox, under “Common Controls” drag and drop 5 button items to the user interface +- Select "button1" > Right-Click > Properties +- Change the attribute "Name" from "button1" to "ConnectToSimulator" +- Change the attribute "text" from "button1" to "Connect To Simulator" +- Change the attribute "Name" from "button2" to "PayWithSignatureAuthorized" +- Change the attribute "text" from "button2" to "Pay With Signature Authorized" +- Change the attribute "Name" from "button3" to "PayWithSignatureDeclined" +- Change the attribute "text" from "button3" to "Pay With Signature Declined" +- Change the attribute "Name" from "button4" to "PayWithPinAuthorized" +- Change the attribute "text" from "button4" to "Pay With Pin Authorized" +- Change the attribute "Name" from "button5" to "PayWithPinDeclined" +- Change the attribute "text" from "button5" to "Pay With Pin Declined" + +**2. Create WebBrowsers** + +Now that we have our 5 buttons let´s create two webBrowsers items to display the merchant receipt as well as the cardholder´s receipt at the end of the transaction. + +- Select View > Toolbox > Common Controls > WebBrowser +- Drag and drop two web browsers to the user interface +- Select View > Toolbox > Common Controls > Label +- Drag and drop two labels to the user interface in order to identify the webBrowser items +- Change the attribute "Name" from the left webBrowser to "MerchantReceiptBrowser" +- Change the attribute "Name" from the right webBrowser to "CardholderReceiptBrowser" +- Change the attribute "Name" from "label1" to "MerchantReceiptLabel" +- Change the attribute "text" from "label1" to "Merchant Receipt :" +- Change the attribute "Name" from "label2" to "CardholderReceiptLabel" +- Change the attribute "text" from "label2" to "Cardholder Receipt :" + +### Let's link our user interface with methods! + +**1. Referencing the user interface(Form1.cs) in MyClass** + +In MyClass.cs, create an instance of Form1 called UIClass and initialize it. Instantiate MyClass and add form1 as a parameter for the Class. + +```csharp + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } +``` +**2. Referencing Myclass in Form1.cs and link methods to the user interface** + +Go to Form1.cs[Design] and double click on the button "Connect To Simulator". By Double Clicking on the "Connect To Simulator" button you created a method called ConnectToSimulator_Click. Create a new instance of MyClass called "my" in Form1.cs then, inside the new method ConnectToSimulator_Click call the Connect() method from MyClass. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + } + } +``` + +Go back to Form1.cs[Design] and double click on each of the other buttons to automatically generate an OnClick method in Form1.cs. Link each of the buttons to the correct methods in MyClass.cs. + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + } + } +``` + +### Let´s display the receipts at the end of a transaction! + +**1. Fetch the cardholder's and merchant receipts from the method EndOfTransaction in MyClass** + +At this point all the buttons are connected but we are still missing to display the receipts in the webBrowsers. First, let´s get the receipts from the method EndOfTransaction in myClass.cs. + +```csharp + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } +``` + +**2. Create the DisplayReceipts method in form1.cs** + +```csharp + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webBrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } +``` + +### Final Result! + +Here is how MyClass.cs and Form1.cs must eventually look like : + +**1. MyClass.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using com.handpoint.api; + namespace GettingStartedWithSimulator + { + class MyClass : Events.Required + { + Hapi api; + private Form1 UIClass; + public MyClass(Form1 form1) + { + InitApi(); + UIClass = form1; + } + + public void InitApi() + { + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + // The api is now initialized. Yay! we've even set a default shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application. + // It prevents other people to connect to your card reader. + } + + public void DeviceDiscoveryFinished(List devices) + { + // Only needed when using a payment terminal + //Here you get a list of Bluetooth payment terminals paired with your PC + // You can also get a list of serial / USB payment terminals attached to your computer + + } + + public void Connect() + { + Device device = new Device("Name", "Address", "Port", ConnectionMethod.SIMULATOR); + api.Connect(device); + } + + public bool PayWithSignatureAuthorized() + { + return api.Sale(new BigInteger("10000"), Currency.GBP); + // amount X00XX where X represents an integer [0;9] --> Signature authorized + } + + public bool PayWithSignatureDeclined() + { + return api.Sale(new BigInteger("10100"), Currency.GBP); + // amount X01XX where X represents an integer [0;9] --> Signature declined + } + + public bool PayWithPinAuthorized() + { + return api.Sale(new BigInteger("11000"), Currency.GBP); + // amount X10XX where X represents an integer [0;9] --> PIN authorized + } + public bool PayWithPinDeclined() + { + return api.Sale(new BigInteger("11100"), Currency.GBP); + // amount X11XX where X represents an integer [0;9] --> PIN declined + } + + public void SignatureRequired(SignatureRequest signatureRequest, Device device) + { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + + + api.SignatureResult(true); // This line means that the cardholder ALWAYS accepts to sign the receipt. + // A specific line will be displayed on the merchant receipt for the cardholder to be able to sign it + } + + public void EndOfTransaction(TransactionResult transactionResult, Device device) + { + UIClass.DisplayReceipts(transactionResult.MerchantReceipt, transactionResult.CustomerReceipt); + } + } + } +``` + +**2. Form1.cs :** + +```csharp + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Data; + using System.Drawing; + using System.Linq; + using System.Text; + using System.Windows.Forms; + namespace GettingStartedWithSimulator + { + public partial class Form1 : Form + { + MyClass my; + public Form1() + { + InitializeComponent(); + my = new MyClass(this); + } + private void ConnectToSimulator_Click(object sender, EventArgs e) + { + my.Connect(); + } + private void PayWithSignatureAuthorized_Click(object sender, EventArgs e) + { + my.PayWithSignatureAuthorized(); + } + private void PayWithSignatureDeclined_Click(object sender, EventArgs e) + { + my.PayWithSignatureDeclined(); + } + private void PayWithPinAuthorized_Click(object sender, EventArgs e) + { + my.PayWithPinAuthorized(); + } + private void PayWithPinDeclined_Click(object sender, EventArgs e) + { + my.PayWithPinDeclined(); + } + + public delegate void UpdateReceiptsCallback(string MerchantReceipt, string CustomerReceipt); + public void DisplayReceipts(string MerchantReceipt, string CustomerReceipt) + { + //Only need to check for one of the webbrowsers + if (MerchantReceiptBrowser.InvokeRequired) + { + UpdateReceiptsCallback d = new UpdateReceiptsCallback(DisplayReceipts); + this.Invoke(d, new object[] { MerchantReceipt, CustomerReceipt }); + } + else + { + MerchantReceiptBrowser.DocumentText = MerchantReceipt; + CardholderReceiptBrowser.DocumentText = CustomerReceipt; + } + } + } + } +```` + +### Let's run our program! + +Run the program by clicking the "play" button, click on "Connect to simulator" and then Click on one of the payment types available and have a look at the receipts! Voila! diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintroduction.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintroduction.md new file mode 100644 index 0000000..20a42d4 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsintroduction.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 1 +id: windowsintroduction +--- + + +# Introduction + +
+
+
+

Windows SDK

+
+
+ + + +
+ +
+
+ +

+ +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler, happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of dark and complex knowledge of the payment industry. + +**Superly secure** + +We take care of the PCI side so you don't have to spend months becoming compliant. +The Handpoint card reader encrypts all sensitive cardholder data so your app does not have to deal with it. + +**Working with the SDK** + +The Handpoint Windows SDK is compatible with .NET Framework Version 4.6.1. + +1. Download the SDK. +2. Create a new windows form project in Visual Studio 2010 (or above) using .Net Framework Version 4.6.1. +3. Add the [HandpointSDK NuGet Package](https://www.nuget.org/packages/HandpointSDK/) to your project. +If you have a DEBUG device [(How to identify DEBUG devices)](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1578401793/How+to+Identify+Between+Development+and+Production+Terminals) please use the package version -beta (prerelease): Example 3.0.0-beta +4. Follow the getting started guide, to get you up and running or dive into the documentation. + +If you have any questions, do not hesitate to [contact us](mailto:support@handpoint.com). \ No newline at end of file diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsobjects.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsobjects.md new file mode 100644 index 0000000..043127c --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsobjects.md @@ -0,0 +1,619 @@ +--- +sidebar_position: 9 +id: windowobjects +--- + + +# Objects + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +** Possible values ** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#23} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Connection Method{#12} + +`ConnectionMethod` Enum + +An enum representing different types of connection methods. + +`BLUETOOTH`, `CLOUD` and `SIMULATOR` are supported for Windows. + +Possible values +`USB` `SERIAL` `BLUETOOTH` `CLOUD` `HTTPS` `WIFI` `ETHERNET` `SIMULATOR` + + +## Connection Status{#18} + +`ConnectionStatus` Enum + +A list of statuses given to a connection. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `Initializing` `NotConfigured` + + +## Currency{#1} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#2} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Constructor** + +Device( String name , String address , String port , ConnectionMethod [*connectionMethod*](#12) , String sharedSecret , int timeout ); + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* |A name to identify the payment terminal| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or "9822032398-PAXA920" for CLOUD (composition of serial number and model of the target device) .| +| `port` Required
*String* | The port to connect to.| +| `connectionMethod` Required
[*ConnectionMethod*](#12) | The type of connection with the device. E.g: Bluetooth, Cloud, Serial, etc.| +| `sharedSecret`
*String* | This parameter can be used to change the default shared secret for the payment terminal| +| `timeout`
*int* | The number of miliseconds after which the connection is considered timed out| + +**Code example** + +```csharp +//Create and init a new HiLite payment terminal +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo payment terminal +Device dev = new Device("CloudDevice", "9822032398-PAXA920", "", ConnectionMethod.CLOUD); +// The address is the composition of the serial number and model ot the target device. +//Example for a PAX A920 device: serial_number - model -> 9822032398-PAXA920 +``` +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Id`
*String* | A unique identifier for the device.| + + +## Device Parameter{#8} + + +`DeviceParameter` Enum + +An enum describing all the available commands to send to a device. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Device Status{#24} + + +`DeviceStatus` Enum + +A class that holds the device status. + +**Properties** + +|Property |Description| +| ----------- | ----------- | +|`SerialNumber`
*String* |Gets the serial number of the device| +|`BatteryStatus`
*String*| Gets the battery status in percentages of the device.| +|`BatterymV`
*String* | Gets the battery milli volts of the device.| +|`BatteryChargingt`
*String*| Gets the battery charging status of the device.| +|`ExternalPower`
*String* | Gets the status of an external power source for the device.| +|`ApplicationName`
*String*| Gets the application name used by the device.| +|`ApplicationVersion`
*String*| Gets the application version number used by the device.| + + + +## Financial Status{#25} + + +`FinancialStatus` Enum + +An enum representing different final statuses of a transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](windowstransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](windowsdevicemanagement.md#get-transaction-status) method. + + + +## Handpoint API (Hapi) factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and to simplify the way to instantiate the Hapi (SDK) object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
*Events.Required* | A listener object to report the required events.| +| `handpointCredentials` Required
[*HandpointCredentials*](#30) | Object containing the user's shared secret and/or Cloud Api Key.| + +**Code example** + +```csharp +//InitApi for HiLite payment terminals +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} + +//InitApi for Cloud payment terminals (PAX/Telpo) +public void InitApi() +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + api = HapiFactory.GetAsyncInterface(this, new HandpointCredentials(sharedSecret, apikey)); + //The api is now initialized. Yay! we've even set a default shared secret and the merchant Api Key! +} +``` + +## Handpoint Credentials{#30} + +`HandpointCredentials` Object + +A class containing information related to the user credentials. + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `SharedSecret`
*String* | `String` the value of the shared secret (provided by Handpoint), only required when using BLUETOOTH as connection method. If using CLOUD this value can be any non-null string.| +| `CloudApiKey`
*String* | `String` the value of the merchant Cloud Api Key (provided by Handpoint), only required when using CLOUD as connection method.| + +**Code example** + +```csharp +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + new HandpointCredentials(sharedSecret); + //We've set a default shared secret! +} + +{ + string sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + string apikey = "This-Is-The-Merchant-Api-Key"; + new HandpointCredentials(sharedSecret, apikey); + //We've set a default shared secret and the merchant Api Key! +} +``` + + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +** Properties ** + + +|Property |Description| +| ----------- | ----------- | +|`DefaultSharedSecret`
*String* |Gets the default shared secret used in the SDK.| +|`LogLevel`
[*LogLevel*](#9) |Gets the current log level of the SDK and payment terminal.| +|`inTransaction`
*bool* |Checks whether the SDK is in transaction or not. True if the SDK is in transaction, false otherwise. This might return a true if there is a communication error between the SDK and payment terminal but the transaction has been completed on the card reader.| +|`SdkVersion`
*String* |Gets the current Sdk version.| +|`IsTransactionResultPending`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This function checks if there is a pending [*Transaction Result*](#14). This field is only updated when connecting to a device. If this function returns true the [*Transaction Result*](#14) (which includes the receipt) can be fetched with hapi.GetPendingTransactionResult();. This function serves the same functionality as the event PendingTransactionResult(Device device), so every time that event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +|`Settings.AutoRecoverTransactionResult`
*boolean* |In case of a communication failure between the device and the API a [*Transaction Result*](#14) might not be delivered to the API. This property can be set to true or false. If set to true, the SDK will automatically fetch the pending [*Transaction Result*](#14) when detected and return it via [*TransactionResultReady*](#11). The function PendingTransactionResult is never invoked if this property is set to true. If set to false PendingTransactionResult will be called when a TransactionResult is pending.| + +**Code example** + +```csharp +//Check if the SDK is in transaction +bool inTransaction = HapiManager.InTransaction(SomeConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.GetLogLevel(); +``` + + + +## Log Level{#9} + + +`LogLevel` Enum + +An enum describing the different levels of logging used in the SDK and the payment terminal. + +**Possible values** + +`None` `Info` `Full` `Debug` + + +## Metadata{#metadata} + +`Metadata` Object + +Object used to echo metadata1-5, in the transaction result, if it was set as an optional parameter in the transaction request . + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemitanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```csharp +Dictionary map = new Dictionary(); + +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); +``` + + +## Operation Start Result{#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +|Property |Description| +| ----------- | ----------- | +|`OperationStarted`
*Boolean* | `true` if the operation has started. `false` otherwise.| +|`TransactionReference`
*String*|The `transactionReference` must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will not return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +|`ErrorMessage`
*String* |Detailed reason for the transaction error.| + + +## Optional Transaction Parameters{#3} + +`OptionalParameters` Object + +A class containing optional transaction parameters now supported by the device. + +**Properties** + + +|Property| Description| +| ----------- | ----------- | +|`Budget`
*String* | **Budget is only available for sale transactions**.
A` String` representing the key for a budget number.A budget number can be used to split up an amount over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to. Example: "03" or "24".| +|`CustomerReference`
*String*|**String CustomerReference is available for all transactions.**
A ` String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 36 characters and received back when the transaction has been processed. Example: "C.nr. 212311".| +|`tokenize`
*Boolean*| Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +|`DuplicateCheck`
*String*| Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The DuplicateCheck functionality is available for the following transactions:** Sale, Sale and Tokenize, Sale Reversal, Refund and Refund Reversal.


The Duplicate Check service is **enabled by default**, if you want to disable it, you must use the `String` "0", for example: ```options.Add(XmlTag.DuplicateCheck.Tag(), "0");```| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| +| `Metadata1`
*String*|**String Metadata1 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata1.Tag(), "Data 1");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata2`
*String*|**String Metadata2 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata2.Tag(), "Data 2");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata3`
*String*|**String Metadata3 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata3.Tag(), "Data 3");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata4`
*String*|**String Metadata4 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata4.Tag(), "Data 4");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `Metadata5`
*String*|**String Metadata5 is available for all transactions.**
A ` String` used to store any required data (max length 250 characters). This information will be echoed inside the Metadata object in the transaction result. Example: ```options.Add(XmlTag.Metadata5.Tag(), "Data 5");```.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](windowsobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + +## Payment Scenario{#26} + +`PaymentScenario` Enum + +An enum representing different types of payment scenarios. + +** Possible values ** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Signature Request{#17} + +`SignatureRequest` Object + +A class containing information about a signature request or verification. + +**Properties** + +|Property| Description| +| ----------- | ----------- | +|Timeout
*Int* |The value of the timeout in seconds.| +|MerchantReceipt
*Html*| The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + + +## Status + +`status` Enum + +An enum containing information about the status of the transaction. + +** Possible values ** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info {#statusInfo} + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + + +|Property |Description| +| ----------- | ----------- | +|`CancelAllowed`
*bool* |A `bool` allowing the user to know if the payment terminal will accept a cancel request.| +|`status`
[*Status*](#status) |A `Status` enum representing the status of the transaction.| +|`message`
*String* |A `String` containing the status message of the transaction.| +|`DeviceStatus`
[*DeviceStatus*](#24) |A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#27} + +`TenderType` Enum + +An enum representing different tender types. + +** Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Terminal Parameters + +`TerminalType` Enum + +An enum describing parameters supported by the payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` +`Language` + + + +## Transaction Result Object{#14} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Parameter | Notes | +| ----------- | ----------- | +| `aid`
*String* | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String* | Acquirer response code| +| `balance`
*BigInteger* | Balance available on the card| +| `budgetNumber`
*String* | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#22) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#23) | The brand of the card| +| `cardToken`
*String* | Token representing the PAN of the card| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters| +| `currency`
[*Currency*](#1) | The currency used for the transaction| +| `customerReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#24) | Status of the payment terminal| +| `dueAmount`
*BigString* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigString* | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#25) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `gratuityAmount` :triangular_flag_on_post:
*BigInteger* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipAmount** field
Gratuity (tip) amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `gratuityPercentage` :triangular_flag_on_post:
*double* | This field will be deprecated in Windows SDK 5.0.0 version, please use the **tipPercentage** field
If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `iad`
*String* | EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String* | Response code from the card issuer| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation| +| `merchantAddress`
*String* | Merchant Address| +| `merchantName`
*String* | Merchant Name| +| `merchantReceipt`
*String* | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata[1-5] was provided as an optional parameter in the transaction request it is echoed unaltered in this object| +| `mid`
*String* | Merchant Identifier| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#26) | Indicates the card entry mode| +| `recoveredTransaction`
*boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#27) | Transaction tender type (credit / debit)| +| `tid`
*String* | Terminal Identifier| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String* | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String* | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#28) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#29) | cardholder verification method, for example "PIN"| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "Data 1", + "metadata2": "", + "metadata3": "", + "metadata4": "", + "metadata5": "" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "gratuityAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "gratuityPercentage": 0, + "recoveredTransaction": false +} +``` + + +## Transaction Type{#28} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `REVERSAL` `UPDATE` `HOST_INIT` `PRINT_RECEIPT` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + +**Code example** + +```csharp +//Currently CLOUD, BLUETOOTH, and SIMULATOR are the only ConnectionMethod available. +public enum ConnectionMethod +{ + USB, + SERIAL, + HTTPS, + WIFI, + ETHERNET, + BLUETOOTH, + CLOUD, + SIMULATOR +} +``` + + +## Verification Method{#29} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +** Possible values ** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` + `MOBILE_PASS_CODE` + + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowsreleasenotes.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsreleasenotes.md new file mode 100644 index 0000000..2962972 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowsreleasenotes.md @@ -0,0 +1,114 @@ +--- +sidebar_position: 2 +id: windowsreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 4.4.0 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](windowsobjects.md#3). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 4.3.1 +**Features:** + +A new `tokenize` parameter is available under [Optional Transaction Parameters](windowsobjects.md#3). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 4.2.0 +**Features:** + +We're excited to announce the latest update to our Windows SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](windowsobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is only available for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 4.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](windowstransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](windowstransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](windowstransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](windowstransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 4.0.0 + +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](windowsdevicemanagement.md#get-transaction-status). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](windowsobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +All financial operations will now be returning an [OperationStartResult](windowsobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: +The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the [TransactionResult](windowsobjects.md#14) object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. + +## 3.4.0 +**Features** + +We are introducing a new feature called [Transaction Metadata](windowsobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 3.3.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v3.3.0 to benefit from this new feature. v3.3.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +Here is an example showing how to disable the duplicate payment check functionality: +```csharp +Dictionary options = new Dictionary(); +options.Add(XmlTag.DuplicateCheck.Tag(), "0"); +hapi.Sale(amount, currency, options); +``` + +## 3.2.6 +- Cloud dependencies update (NewtonSoft Lib) + +## 3.2.5 + +**Fixes:** +- Nullpointer Exception on Cloud connect without network connection. +- Cloud dependencies update. +- Connection handling on transitions states: Connecting and Disconnecting. +- Automatic Cloud reconnection handling. +- Unable to manually disconnect during a transaction. + + +## 3.2.4 +**Fixes:** +- `SignatureResult` method. Signature result is always true no matter what is passed to the method. + +## 3.2.3 +**Fixes:** +- Crash on signature result (DATECS) + +## 3.2.1 +- Improved SDK reconnection logic in case of network unstability. + +## 3.2.0 + +**CLOUD Features:** + +- Mail Order/Telephone Order (MoTo). +- StopCurrentTransaction operation. + +## 3.1.7 + +**Fixes:** + +- CLOUD: Improved initial retry mechanism for triggering transactions. +- CLOUD: Increased initial timeout for triggering transactions. + + + diff --git a/windows_versioned_docs/version-Windows SDK 4.4.0/windowstransactions.md b/windows_versioned_docs/version-Windows SDK 4.4.0/windowstransactions.md new file mode 100644 index 0000000..dff9125 --- /dev/null +++ b/windows_versioned_docs/version-Windows SDK 4.4.0/windowstransactions.md @@ -0,0 +1,938 @@ +--- +sidebar_position: 5 +id: windowstransactions +--- + + +# Transaction Types + +:::caution +Since [**Windows SDK 3.3.0**](windowsreleasenotes#330) the Duplicate Check service it will be **enabled by default** when Handpoint Payments app **v4.0.0.** or higher is used. (Handpoint **Android SDK 7.0.0** or higher). +::: + +## Sale + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In it's simplest form you only have to pass the **amount** and **currency** but it also accepts a map with optional parameters. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + + +**Code example** + +```csharp +// Basic +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.Sale(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +*** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale And Tokenize Card + +`SaleAndTokenizeCard` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Initiate a sale for 10.00 in Great British Pounds +api.SaleAndTokenizeCard(new BigInteger("1000"),Currency.GBP); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.SaleAndTokenizeCard(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale Reversal + +`SaleReversal` Method + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + +**Code example** + +```csharp +//Initiate a reversal for 10.00 Pounds +api.SaleReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund + +`Refund` Method + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with optional parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID`
*String* | Id of the original sale transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Initiate a refund for 10.00 in Great British Pounds +api.Refund(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +api.Refund(new BigInteger("1000"), Currency.EUR, map); +``` + +#### Events invoked +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Refund Reversal + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with optional parameters. Note that transactions can only be reversed within the same day as the transaction was made. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the transaction.| +| `originalTransactionID` Required
*String* | Id of the original refund transaction (EFTTransactionID)| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3)| + + +**Code example** + +```csharp +//Initiate a refund reversal for 10.00 in Great British Pounds +api.RefundReversal(new BigInteger(1000),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry' +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*Currency* | Currency of the transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +// Basic MoTo Sale +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.MotoSale(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required*Currency* | Currency of the transaction.| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowobjects#3) (Customer reference, [Metadata](windowsobjects.md#metadata), [Money Remittance Options](windowsobjects.md#money-remittance-options),...). This object can be empty if no options are required.| + +**Code example** + +```csharp +//Basic MoTo Refund +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR); + +this.Hapi.MotoRefund(new BigInteger(1000), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + + +//With Options +Dictionary dic = new Dictionary(); +dic.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.MoneyRemittanceCountryCode.Tag(), "USA"); +map.Add(XmlTag.MoneyRemittanceFullName.Tag(), "John Doe"); + +this.Hapi.MotoRefund(new BigInteger("1000"), Currency.EUR, dic); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.MotoReversal("00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +|`currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map` *Map* | A map including optional transaction parameters| + +**Code example** + +```csharp +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.moToPreAuthorization(new BigInteger(1000), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Print Receipt + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)| + +**Code example** + +```csharp +// string validReceipt = '...'; +bool success = api.PrintReceipt(validReceipt); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the receipt was sent to the printer, false otherwise| + + +## Signature Result + +`SignatureResult` Method + +A signatureRequired event is invoked during a transaction when a signature verification is required, for example when a payment is done with a swiped or chip and signature card. The merchant is required to ask the cardholder for signature and approve (or decline) the transaction. signatureResult tells the payment terminal if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the payment terminal. Note that this event is only required for an HiLite integration and can be safely ignored for a PAX or Telpo integration. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts customer signature| + +**Code example** + +```csharp +//Receiving a SignatureRequest from the SDK. +public void SignatureRequired(SignatureRequest signatureRequest, Device device) +{ + //If you accept the signature + api.SignatureResult(true); +} +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + + +## Tip Adjustment + +`TipAdjustment` Method + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. This functionality is limited to HiLite terminals. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Id of the original sale transaction (EFTTransactionID) | + + +**Code example** + +```csharp +//Initiate a tip adjustment for $10.00 +Task result = hapi.TipAdjustment(BigInteger.Parse("1000"), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); +FinancialStatus status = result.Result; +if (status != FinancialStatus.FAILED) +{ + if (status == FinancialStatus.AUTHORISED) + { + //Success! + } + else + { + //Declined + } +} +``` + +**Returns** + +Result of the tip adjustment transaction, this is an asynchronous method that returns a task called ``, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor)| + + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +#### Parameters + +| Parameter | Notes | +| ----------- | ----------- | +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +//Initiates a card tokenization operation. +api.TokenizeCard(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [OperationStartResult](windowsobjects.md#OperationStartResult)| Object containing information about the financial operation started. Most specifically the transactionReference which must be saved on your end in case you do not get back the transaction result object at the end of the transaction. The transactionReference will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Stop Current Transaction + +`StopCurrentTransaction` Method + +This method attempts to cancel the current transaction on the payment terminal. Note that operations can only be cancelled before requests are sent to the gateway. There is a flag called [cancelAllowed](windowobjects#status-info) in the currentTransactionStatus event that can be used to check if the transaction is in a state allowing the transaction to be cancelled. + + +**Code example** + +```csharp +this.Hapi.StopCurrentTransaction(); +``` + +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully sent to the payment terminal| + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorization(new BigInteger("1000"), Currency.EUR, map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + + +**Code example** + +```csharp +// Basic PreAuth Increase +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationIncrease(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); + +// Basic PreAuth Decrease +this.Hapi.PreAuthorizationIncrease(new BigInteger("-1000"), Currency.EUR, ""00000000-0000-0000-0000-000000000000"); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](windowsobjects.md#1) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationCapture(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will released the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](windowstransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](windowsobjects.md#25) -> [AUTHORISED](windowsobjects.md#25)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction| +| `map`
*Map* | A map including [*optional transaction parameters.*](windowsobjects.md#3)| + +**Code example** + +```csharp +// Basic +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +// With options +Dictionary map = new Dictionary(); +map.Add(XmlTag.CustomerReference.Tag(), "YourCustomerReference"); +map.Add(XmlTag.Metadata1.Tag(), "Data 1"); + +this.Hapi.PreAuthorizationReversal("00000000-0000-0000-0000-000000000000", map); +``` +#### Events invoked + +**[*currentTransactionStatus*](windowsevents.md#4)** + +This event gets statuses from the payment terminal during the transaction, for example: 'waiting for card' or 'waiting for PIN entry'. +**** + +**[*signatureRequired*](windowsevents.md#5)** + +This event is invoked if the card issuer requires the cardholder to sign the transaction receipt. +**** + +**[*endOfTransaction*](windowsevents.md#6)** + +This event is invoked when the transaction is completed, it contains the transaction result and receipts. +**** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](windowsobjects.md#OperationStartResul)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/windows_versioned_sidebars/version-Windows SDK 4.4.0-sidebars.json b/windows_versioned_sidebars/version-Windows SDK 4.4.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/windows_versioned_sidebars/version-Windows SDK 4.4.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/windows_versions.json b/windows_versions.json index 7b8e0b2..3137b3c 100644 --- a/windows_versions.json +++ b/windows_versions.json @@ -1,4 +1,5 @@ [ + "Windows SDK 4.4.0", "Windows SDK 4.3.1", "Windows SDK 4.2.0", "Windows SDK 4.1.0", From f39eb5cde10472d2d5d51bb2eac8f0b7812741e0 Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:42:56 +0200 Subject: [PATCH 110/115] Update Android SDK repo information (#147) Updating documentation to remove Maven Central information, as the only repo to use is Nexus --- android/androidintegrationguide.md | 40 +++++++----------- android/androidintroduction.md | 12 ------ .../androidintegrationguide.md | 18 ++------ .../androidintroduction.md | 42 ++----------------- 4 files changed, 20 insertions(+), 92 deletions(-) diff --git a/android/androidintegrationguide.md b/android/androidintegrationguide.md index 3735367..d9114a4 100644 --- a/android/androidintegrationguide.md +++ b/android/androidintegrationguide.md @@ -57,9 +57,9 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: **2. SDK distribution** The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. -- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. -- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. +- If you are integrating your software with a **PAX debug terminal** you will need to get the **release candidates 7.xxxx.xx-RC** SDK. +- If you are integrating your software with a **PAX production terminal** you will need to get the **production** SDK. +- If you are integrating your software with an **HiLite terminal** you will need to get the **production** SDK. The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. @@ -136,18 +136,6 @@ android { } ``` -**Maven Settings** - -For production terminals: - -```xml - - com.handpoint.api - sdk - [7.1001.0,) - aar - -``` :::tip If using AndroidX you will need to switch the following flags to true:

android.enableJetifier=true

@@ -357,12 +345,12 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ```groovy android { - defaultConfig { - minSdkVersion 22 //Required to support all PAX & Telpo models - targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need //to add android:exported="true" or android:exported="false" in your activities - multiDexEnabled true - } + multiDexEnabled true + } packagingOptions { pickFirst '**/*.so' @@ -613,12 +601,12 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ```groovy android { - defaultConfig { - minSdkVersion 22 //Required to support all PAX & Telpo models - targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need //to add android:exported="true" or android:exported="false" in your activities - multiDexEnabled true - } + multiDexEnabled true + } packagingOptions { pickFirst '**/*.so' @@ -829,4 +817,4 @@ public class HandpointDelegate implements Events.MposRequired, Events.Connection Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. -Explore the rest of the documentation to see more transaction types supported and possibilities. +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android/androidintroduction.md b/android/androidintroduction.md index 360e509..97e51a7 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -154,18 +154,6 @@ android { } ``` -### Maven Settings - -For production terminals: - -```xml - - com.handpoint.api - sdk - [7.1001.0,) - aar - -``` :::tip If using AndroidX you will need to switch the following flags to true:

android.enableJetifier=true

diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md index f175114..7a9d6a0 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidintegrationguide.md @@ -57,9 +57,9 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: **2. SDK distribution** The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. -- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. -- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. +- If you are integrating your software with a **PAX debug terminal** you will need to get the **release candidates 7.xxxx.xx-RC** SDK. +- If you are integrating your software with a **PAX production terminal** you will need to get the **production** SDK. +- If you are integrating your software with an **HiLite terminal** you will need to get the **production** SDK. The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. @@ -136,18 +136,6 @@ android { } ``` -**Maven Settings** - -For production terminals: - -```xml - - com.handpoint.api - sdk - [7.1001.0,) - aar - -``` :::tip If using AndroidX you will need to switch the following flags to true:

android.enableJetifier=true

diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md index 71f733b..5e2a9ce 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidintroduction.md @@ -45,8 +45,8 @@ We take care of PCI compliance so you can be kept out of PCI scope. The Handpoin ### SDK distribution The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.1-RC.0-SNAPSHOT** -- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.1** +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.3-RC.1-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.3** If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. @@ -82,24 +82,6 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -#### For production terminals (Maven): -```groovy - //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:7.x.x' -``` -In the `gradle.build` (Top-level build file) for production terminals (Maven): - - ```groovy - allprojects { //Handpoint Production SDK (Production terminals) - repositories { - google() - mavenCentral() - maven { url 'https://jitpack.io' } - } - } - ``` - -#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' @@ -107,7 +89,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy - allprojects { //Handpoint Staging/Development SDK (Debug terminals) + allprojects { repositories { google() mavenCentral() @@ -151,24 +133,6 @@ android { } ``` -### Maven Settings - -For production terminals: - -```xml - - com.handpoint.api - sdk - [7.1001.0,) - aar - -``` -:::tip -If using AndroidX you will need to switch the following flags to true:

-android.enableJetifier=true

-android.useAndroidX=true -::: - It is time to visit our **[Integration Guides](androidintegrationguide)** section. If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. From a004ebb95034fc22d1c9b628f22f2ea7d13c37a0 Mon Sep 17 00:00:00 2001 From: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Date: Fri, 17 Oct 2025 08:43:07 +0200 Subject: [PATCH 111/115] CUS-655 (#148) Update Android SDK documentation. Add missing currency parameter on tipAdjustment transaction --- android/androidtransactions.md | 3 ++- .../version-Android SDK 7.1008.1/androidtransactions.md | 3 ++- .../version-Android SDK 7.1008.3/androidtransactions.md | 3 ++- .../version-Android SDK 7.1008.4/androidtransactions.md | 3 ++- .../version-Android SDK 7.1008.5/androidtransactions.md | 3 ++- .../version-Android SDK 7.1008.6/androidtransactions.md | 3 ++- .../version-Android SDK 7.1009.5/androidtransactions.md | 3 ++- .../version-Android SDK 7.1010.1/androidtransactions.md | 3 ++- .../version-Android SDK 7.1010.2/androidtransactions.md | 3 ++- .../version-Android SDK 7.1010.3/androidtransactions.md | 3 ++- .../version-Android SDK 7.1010.5/androidtransactions.md | 3 ++- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/android/androidtransactions.md b/android/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1008.1/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1008.3/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1008.4/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1008.5/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md index dab62b1..7aa3121 100644 --- a/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1008.6/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md index 59744d3..806c3ab 100644 --- a/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1009.5/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md index a074b1e..7df8589 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1010.1/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md index a074b1e..7df8589 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1010.2/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md index a074b1e..7df8589 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1010.3/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) diff --git a/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md index a074b1e..7df8589 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md +++ b/android_versioned_docs/version-Android SDK 7.1010.5/androidtransactions.md @@ -645,6 +645,7 @@ The code example provided depends on RxJava, take a look a their documentation t | Parameter | Notes | | ----------- | ----------- | | `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | | `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| **Code example** @@ -653,7 +654,7 @@ The code example provided depends on RxJava, take a look a their documentation t Observable.fromCallable(new Callable() { @Override public FinancialStatus call() throws Exception { - return api.tipAdjustment(new BigDecimal(1000), "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); } }) .subscribeOn(Schedulers.io()) From 39099afa33b3df954b555c85b91e068cb69bce9e Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Wed, 22 Oct 2025 13:04:12 +0200 Subject: [PATCH 112/115] DOCWEB-85 (#149) * Updating the base documentation for Android SDK * Adding documentation for Android SDK 7.1010.6 * Updating main Android SDK documentation * Adding documentation for REST API 2.22.3 * Updating main REST API documents * Adding documentation for REST API 2.22.4 version * Adding documentation for REST API 2.23.0 version --- android/androideventlisteners.md | 24 +- android/androidintroduction.md | 41 +- android/androidmigrationguide.md | 28 +- android/androidobjects.md | 30 +- android/androidreleasenotes.md | 172 ++ android/androidtransactions.md | 1064 ++++++++- .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 820 +++++++ .../androidintroduction.md | 138 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 475 ++++ .../androidtransactions.md | 2028 +++++++++++++++++ ...version-Android SDK 7.1010.6-sidebars.json | 8 + android_versions.json | 1 + restapi/restendpoints.md | 295 ++- restapi/restobjects.md | 25 +- restapi/restreleasenotes.md | 29 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.22.3/restdownloads.md | 10 + .../version-REST API 2.22.3/restendpoints.md | 746 ++++++ .../restintroduction.md | 55 + .../version-REST API 2.22.3/restobjects.md | 825 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 112 + .../version-REST API 2.22.3/restsandbox.md | 44 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.22.4/restdownloads.md | 10 + .../version-REST API 2.22.4/restendpoints.md | 746 ++++++ .../restintroduction.md | 55 + .../version-REST API 2.22.4/restobjects.md | 825 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 117 + .../version-REST API 2.22.4/restsandbox.md | 44 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.23.0/restdownloads.md | 10 + .../version-REST API 2.23.0/restendpoints.md | 746 ++++++ .../restintroduction.md | 55 + .../version-REST API 2.23.0/restobjects.md | 825 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 122 + .../version-REST API 2.23.0/restsandbox.md | 44 + .../version-REST API 2.22.3-sidebars.json | 8 + .../version-REST API 2.22.4-sidebars.json | 8 + .../version-REST API 2.23.0-sidebars.json | 8 + restapi_versions.json | 3 + 49 files changed, 13195 insertions(+), 191 deletions(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.6/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.6-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.3/restsandbox.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.22.4/restsandbox.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.0/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.22.3-sidebars.json create mode 100644 restapi_versioned_sidebars/version-REST API 2.22.4-sidebars.json create mode 100644 restapi_versioned_sidebars/version-REST API 2.23.0-sidebars.json diff --git a/android/androideventlisteners.md b/android/androideventlisteners.md index dd79145..4eae6c1 100644 --- a/android/androideventlisteners.md +++ b/android/androideventlisteners.md @@ -20,9 +20,9 @@ You must provide a class implementing this interface when initializing the SDK f public final class EventHandler implements Events.SmartposRequired { @Override - public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } @Override - public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } @Override public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } @Override @@ -49,14 +49,14 @@ You must provide a class implementing this interface when initializing the SDK f ```java public final class EventHandler implements Events.MposRequired { - @Override - public void deviceDiscoveryFinished(List devices) { ... } @Override - public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } @Override - public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } @Override - public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } @Override public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } @Override @@ -82,14 +82,14 @@ You must provide a class implementing this interface when initializing the SDK w ```java public final class EventHandler implements Events.PosRequired { - @Override - public void deviceDiscoveryFinished(List devices) { ... } @Override - public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } @Override - public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } @Override - public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } @Override public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } @Override diff --git a/android/androidintroduction.md b/android/androidintroduction.md index 97e51a7..5e2a9ce 100644 --- a/android/androidintroduction.md +++ b/android/androidintroduction.md @@ -14,14 +14,11 @@ id: androidintroduction

Android SDK

- -
@@ -47,11 +44,11 @@ We take care of PCI compliance so you can be kept out of PCI scope. The Handpoin ### SDK distribution -The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. -- If you are integrating your software with a **PAX debug terminal** you will need to get the SDK from **Nexus**. -- If you are integrating your software with a **PAX production terminal** you will need to get the SDK from **Maven Central**. -- If you are integrating your software with an HiLite terminal you will need to get the SDK from **Maven Central**. +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.3-RC.1-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.3** +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. The latest version is compiled with java **1.8** @@ -85,24 +82,6 @@ We **strongly** recommend you add the following to your `AndroidManifest.xml`: ### Gradle Settings -#### For production terminals (Maven): -```groovy - //Handpoint Production SDK (Production terminals) - implementation 'com.handpoint.api:sdk:7.x.x' -``` -In the `gradle.build` (Top-level build file) for production terminals (Maven): - - ```groovy - allprojects { //Handpoint Production SDK (Production terminals) - repositories { - google() - mavenCentral() - maven { url 'https://jitpack.io' } - } - } - ``` - -#### For debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy //Handpoint Staging/Development SDK (Debug terminals) implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' @@ -110,7 +89,7 @@ In the `gradle.build` (Top-level build file) for production terminals (Maven): In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: ```groovy - allprojects { //Handpoint Staging/Development SDK (Debug terminals) + allprojects { repositories { google() mavenCentral() @@ -154,12 +133,6 @@ android { } ``` -:::tip -If using AndroidX you will need to switch the following flags to true:

-android.enableJetifier=true

-android.useAndroidX=true -::: - It is time to visit our **[Integration Guides](androidintegrationguide)** section. If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android/androidmigrationguide.md b/android/androidmigrationguide.md index 47511b2..0811895 100644 --- a/android/androidmigrationguide.md +++ b/android/androidmigrationguide.md @@ -75,8 +75,8 @@ public class HandpointDelegate implements ```java class KotlinClient: Events.Required, - Events.CurrentTransactionStatus, - Events.ConnectionStatusChanged { + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { ``` @@ -88,11 +88,11 @@ class KotlinClient: ```java public class HandpointDelegate implements - Events.SmartposRequired, - Events.CurrentTransactionStatus, - Events.ConnectionStatusChanged, - Events.EndOfTransaction, - Events.TransactionResultReady { + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { ``` @@ -129,7 +129,7 @@ public class HandpointDelegate implements ```java class KotlinClient: - Events.Required, + Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { ``` @@ -145,11 +145,11 @@ class KotlinClient: public class JavaClient implements Events.MposRequired, Events.ConnectionStatusChanged, - Events.CurrentTransactionStatus, - Events.SignatureRequired, - Events.EndOfTransaction, - Events.DeviceDiscoveryFinished, - Events.TransactionResultReady { + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { ``` @@ -186,7 +186,7 @@ public class HandpointDelegate implements ```java class KotlinClient: - Events.Required, + Events.Required, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus { ``` diff --git a/android/androidobjects.md b/android/androidobjects.md index a9bae86..ec9cd65 100644 --- a/android/androidobjects.md +++ b/android/androidobjects.md @@ -166,14 +166,14 @@ An enum representing all the supported acquirers for merchant authentication. ```java public enum Acquirer { AMEX, - BORGUN, - EVO, - OMNIPAY, - POSTBRIDGE, - INTERAC, - TSYS, - VANTIV, - SANDBOX + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX } ``` @@ -431,9 +431,9 @@ A class containing the credentials used to communicate with the payment terminal ```java { - String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); - //We've even set a default shared secret! + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! } ``` @@ -461,9 +461,9 @@ getAsyncInterface( Events.Required requiredListener , Context context , Handpoin //InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT public void InitApi() { - String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; - api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); - //The api is now initialized. Yay! we've even set a default shared secret + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret } ``` @@ -736,7 +736,7 @@ MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); `OperationDto` Object -Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize and Modify operation. +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. **Properties** diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 6d34628..4d22296 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,178 @@ id: androidreleasenotes Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: + +## 7.1010.6 +**Features**: + +- Partial reversals are supported now + +- Support for PAX A3700 reader has been added + +**Fixes** + +- Processing misalignment between SDK and Gateway has been fixed + + +## 7.1010.5 +**Features**: + +A new `cardPresent` flag is supported in Integrated mode, which comes from our [REST API](/restapi/restintroduction) or its related Cloud clients [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). This new flag allows to indicate the payments flow that a Reversal operation will imply an actual present card. Please see [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for further information on the purpose of this flag. + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + ## 7.1005.0 **Features**: diff --git a/android/androidtransactions.md b/android/androidtransactions.md index 7aa3121..7df8589 100644 --- a/android/androidtransactions.md +++ b/android/androidtransactions.md @@ -721,88 +721,7 @@ Invoked when the terminal finishes processing the transaction. | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| -## Tokenize And Modify -`tokenizedOperation` -A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This operation is very useful for loyalty scenarios, a unique token for the card is delivered to your application in the middle of the transaction so you can lookup in your own loyalty engine if the cardholder qualifies for a discount. If the cardholder does qualify for a discount then the amount of the transaction can be modified (decreased) before the transaction is sent for processing. - -**Parameters** - - -| Parameter | Notes | -| ----------- | ----------- | -| `currency` Required
[*Currency*](androidobjects.md#13)| Currency of the charge| -| `operationDto` Required
[*OperationDto*](androidobjects.md#operation-dto)| An object containing information about the financial operation being performed after the initial tokenization, if not specified it will default to "sale"| -| `options` Required
[*SaleOptions*](androidobjects.md#4) / [*RefundOptions*](androidobjects.md#6)| An object to store all the customization options for a sale or a refund.| - -```java -//Tokenize a card and modifies the amount of a sale operation. -//Performs a tokenization of the card and sends the token back to you through the Events.CardTokenized event. -//Once you wish to continue the operation, execute the resume method of the object sent through the Events.CardTokenized event, along with the data for the financial operation you wish perform. -//The financial operation will be executed and the result will be received through the Events.Required EndOfTransaction event. - -Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); - -SaleOptions options = new SaleOptions(); -options.setMetadata(metadata); - -api.tokenizedOperation(Currency.GBP,options); - -// To get the token and integrate the payment flow with your loyalty engine, implement the Events.CardTokenization interface. -class LoyaltyEngine : Events.CardTokenization { - - override fun cardTokenized(callback: ResumeCallback, cardTokenizationData: CardTokenizationData) { - // Call the loyalty engine and apply discounts based on cardTokenizationData - val finalAmount: BigInteger = ... // Calculate the final amount with discounts - // Call resume to continue the sale operation - val sale = OperationDto.Sale(finalAmount, Currency.EUR, getSaleOptions()) - // Resume the operation using the callback - callback.resume(sale) - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -//Tokenizes a card and executes a Refund, Sale Reversal or Refund Reversal. -//This operation executes the financial operation using the OperationDto parameter, in the example below a refund is processed. -//The result of both the tokenization and refund operations will be received through the Events.Required EndOfTransaction event. - -Metadata metadataRefund = new Metadata("This", "is", "a", "Refund", ":D"); - -RefundOptions refundOptions = new RefundOptions(); -refundOptions.setMetadata(metadataRefund); -OperationDto.Refund operation = new OperationDto.Refund(amount, currency, null, refundOptions); - -api.tokenizedOperation(Currency.GBP,operation,options); -``` - -**Events invoked** - -[**currentTransactionStatus**](androideventlisteners.md#14) - -Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). -*** - - -[**cardTokenization**](androideventlisteners.md#card-tokenization) - -Invoked when the terminal finishes processing the transaction. - -*Note*: It will only be invoked in the case of a Sale operation. Refund and Reversal operations will be received straight throught the Events.Required EndOfTransaction event. -*** - -[**endOfTransaction**](androideventlisteners.md#16) - -Invoked when the terminal finishes processing the transaction. -*** - -**Returns** - -| Parameter | Notes | -| ----------- | ----------- | -| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| - - ## Card PAN{#13} `cardPan` @@ -1124,3 +1043,986 @@ Invoked when the terminal finishes processing the transaction. | Parameter | Notes | | ----------- | ----------- | | *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.6/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.6/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.6/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidintegrationguide.md new file mode 100644 index 0000000..d9114a4 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidintegrationguide.md @@ -0,0 +1,820 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the **release candidates 7.xxxx.xx-RC** SDK. +- If you are integrating your software with a **PAX production terminal** you will need to get the **production** SDK. +- If you are integrating your software with an **HiLite terminal** you will need to get the **production** SDK. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidintroduction.md new file mode 100644 index 0000000..5e2a9ce --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidintroduction.md @@ -0,0 +1,138 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.3-RC.1-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.3** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md new file mode 100644 index 0000000..4d22296 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md @@ -0,0 +1,475 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + + +## 7.1010.6 +**Features**: + +- Partial reversals are supported now + +- Support for PAX A3700 reader has been added + +**Fixes** + +- Processing misalignment between SDK and Gateway has been fixed + + +## 7.1010.5 +**Features**: + +A new `cardPresent` flag is supported in Integrated mode, which comes from our [REST API](/restapi/restintroduction) or its related Cloud clients [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). This new flag allows to indicate the payments flow that a Reversal operation will imply an actual present card. Please see [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for further information on the purpose of this flag. + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidtransactions.md new file mode 100644 index 0000000..7df8589 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidtransactions.md @@ -0,0 +1,2028 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.6-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.6-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.6-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 761c2af..6106d32 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.6", "Android SDK 7.1010.5", "Android SDK 7.1010.3", "Android SDK 7.1010.2", diff --git a/restapi/restendpoints.md b/restapi/restendpoints.md index d9dfd31..163cdf3 100644 --- a/restapi/restendpoints.md +++ b/restapi/restendpoints.md @@ -22,7 +22,7 @@ Initializes the REST API client and returns the list of payment terminals associ | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | Returns @@ -51,14 +51,15 @@ RESPONSE: { "merchant_id_alpha": "merchantID", "serial_number": "082104578", - "customerReference": "op15248", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", "terminal_type": "PAXA920" } ] ``` - - +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: @@ -76,7 +77,7 @@ POST endpoint used to send a financial operation to the payment terminal. The tr | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | @@ -92,6 +93,9 @@ POST endpoint used to send a financial operation to the payment terminal. The tr **Code Example** +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: ```shell Operation executed using CLI tool CURL: @@ -164,7 +168,7 @@ GET endpoint used to retrieve transaction results from the payment terminal. In | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | @@ -270,7 +274,7 @@ Note: If two tip adjustments are sent for the same original transaction, only th | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant.| +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | | `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | | `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | @@ -354,8 +358,13 @@ The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) | Parameter | Notes | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: **Responses** @@ -436,21 +445,30 @@ The `https://transactions.handpoint.io/transactions/{transactionReference}/statu **Selector Values** | Selector | Description | -| ----------- | ----------- | -| all |Returns the status of all transactions associated with the given `transactionReference`. | -| {index} |Returns the status of a specific transaction identified by its index in the sequence of transactions associated with the `transactionReference`. The index is a 1-based integer, where 1 represents the first transaction, 2 the second, and so on.| +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + +:::caution **Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: **Parameters** | Parameter | Description | | ----------- | ----------- | -| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. | -| `Path: transactionReference` Required
*String* | The `transactionReference` is a unique [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| | `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: **Responses** @@ -478,4 +496,251 @@ The `https://transactions.handpoint.io/transactions/{transactionReference}/statu curl -X GET \ -H "ApiKeyCloud: your-api-key" \ "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" - ``` \ No newline at end of file + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 68af6f1..8579f4b 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -15,7 +15,7 @@ An enum representing the supported acquirers for merchant authentication. **Possible values** -`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` ## Balance @@ -317,7 +317,7 @@ An enum representing different types of operations. Possible Values: -`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `update` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` @@ -335,9 +335,8 @@ Possible Values: | `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | | `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | -| `update`
*String* | The update operation checks for new software or configuration updates and initiates a download if required. | | `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | -| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is online. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | | `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | | `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | | `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | @@ -570,6 +569,8 @@ An object to store information about the request sent to the payment terminal. | `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| | `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| | `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| **Code example** @@ -822,19 +823,3 @@ An enum representing the possible verification methods used during the transacti Possible values: `UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` - - - - - - - - - - - - - - - - diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 89b170a..01faf55 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,35 @@ id: restreleasenotes Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: +## 2.23.0 +**Bug fixes:** + +Support for MOTO operations in the Get Transaction Status service has been added + +## 2.22.4 +**Bug fixes:** + +Internal performance issues have been solved. + +## 2.22.3 +**Bug fixes:** + +A external vulnerability has been addressed. + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + ## 2.17.0 **Features:** diff --git a/restapi_versioned_docs/version-REST API 2.22.3/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.22.3/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restdownloads.md b/restapi_versioned_docs/version-REST API 2.22.3/restdownloads.md new file mode 100644 index 0000000..653b02c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restendpoints.md b/restapi_versioned_docs/version-REST API 2.22.3/restendpoints.md new file mode 100644 index 0000000..163cdf3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restendpoints.md @@ -0,0 +1,746 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", + "terminal_type": "PAXA920" + } + ] +``` + +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + + +:::caution +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restintroduction.md b/restapi_versioned_docs/version-REST API 2.22.3/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restobjects.md b/restapi_versioned_docs/version-REST API 2.22.3/restobjects.md new file mode 100644 index 0000000..8579f4b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restobjects.md @@ -0,0 +1,825 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.22.3/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.22.3/restreleasenotes.md new file mode 100644 index 0000000..3774764 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restreleasenotes.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 2.22.3 +**Bug fixes:** + +A external vulnerability has been addressed. + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.22.3/restsandbox.md b/restapi_versioned_docs/version-REST API 2.22.3/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.3/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.4/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.22.4/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restdownloads.md b/restapi_versioned_docs/version-REST API 2.22.4/restdownloads.md new file mode 100644 index 0000000..653b02c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restendpoints.md b/restapi_versioned_docs/version-REST API 2.22.4/restendpoints.md new file mode 100644 index 0000000..163cdf3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restendpoints.md @@ -0,0 +1,746 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", + "terminal_type": "PAXA920" + } + ] +``` + +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + + +:::caution +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restintroduction.md b/restapi_versioned_docs/version-REST API 2.22.4/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restobjects.md b/restapi_versioned_docs/version-REST API 2.22.4/restobjects.md new file mode 100644 index 0000000..8579f4b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restobjects.md @@ -0,0 +1,825 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.22.4/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.22.4/restreleasenotes.md new file mode 100644 index 0000000..9651679 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restreleasenotes.md @@ -0,0 +1,117 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 2.22.4 +**Bug fixes:** + +Internal performance issues have been solved. + +## 2.22.3 +**Bug fixes:** + +A external vulnerability has been addressed. + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.22.4/restsandbox.md b/restapi_versioned_docs/version-REST API 2.22.4/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.22.4/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.23.0/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.23.0/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 zcmd6MbyOY8^6thp!5xBYfQ<)tcXtWy?!g1W-Q8U_Zo%CxXmEFT=aF;IyZ5a7e(&G6 z-puOhny>1s>gukwdi6|*ysX# zLP&^6-oe(y+{zdL5D!UEgHcx+!pzi)jgFoKM~O!LhL(@UF9}Qc-B-CwR2&?Rygwk@ zKnx2*yCv8_L`?);2Z1OobYUcS;mJTiL<0*UH20E%Ec>YavhB)iZ`@}h{b3@-(e$(p z!q){!j%G~6888^PJ+etEm~5yxot*E&4_zp)(HS<7B=y_gehM(m|K#fK13@%=TUr}? zl=bqaat$fSK?pFy@5KS<;6vJ^0G!`=me3Lca(~&dlIxZBIugw#bwLvA7W8V+v?_%# zD>qfIQ8H#iTo?mbin%js5dak)ljF4OrUIWTCXibsAr0UFi#O%O zf_uoD8K*2fL<`x|5g4`U_Lc2(wIvCC%xZrwu17f)N z!C6eFB{&tNk02T3WtTniOPioP;6x9)qO^>8@c4{wpD+d@Q!pJSm!G~>?K&zJQB(?A zE?eX|YM;BIr`*gvSO&`w!jnMb0?PT;duj%soCm z7CVe#mwz#>+8ek}KPv_LTF*pfE(jh2T%frkGkS2VIXinJ^=}qLj)PH=Kp@JOGD{*& zPaj^6XtC!gH*RNXWAYu)EQkP-vXh0R~tIQUO|V$da$%im7X3s*Fo?H}7Mi21 zOvox?J+(oFV4SC5M#A}NOpr3~$G)c%oMxnIZp)PBHTyTPw#bGY;FJyG*HmnX+Rk)F z%>FKeY8G0wIQ`lx)N;hKUW+Q|`}9f!Yjw(76v|Df^boEd4Ezwv4Np%dUIe}H${yFv z`g@6Inpfnr?haHlNVM;0T~VFn;lxHLg~*|B#sMb*LIFy4z?96&~-uy$bDnQhYCjv z;*~6@im2|WY*|@Z=~%s3#VkWv_skM4Pp7%d9^|h`RiX~XcjN~YFlNYS2xce_tq-+u zBTS?a3Jaz#&85s#>d@+7>ORr^Obo+Rlgeh*DibVIJqn%sY+ch3!KUT$-6h8*?oZdS$JxV$}o3focW13_>XAx&hwvgAi>&=evW3_${{)uaTtDz zx78onpBGVtZOg)Iyv(8OQ~W0XIvJbu6tv1HAcHTnDN~qc#oBE4%i6*OSD%Je$MRcu z-E_DN{0wQW+y<8*@F=fj~lUlY2Ea;Jo&{HOO`4dRg=* zMl)+uo4u>kUW;0j-c`1HfXC=<@txbr!8Y~v^1k~>*eUCSdAD&ToWxsOvvt?o|0ZD zPs>75M^;BJ4Wy;E(pm7g8#ymOKRgG)Rt6uS$ixH;77y;kd}%J!=4}jJV*O>hJsLxq zSF8Z1aFqK=giCZJ7f&=NPc%}K<4`wTCY-F09<$fMP_2J8sx~YQ|8B`_bH8Z{BQLAJ zrEembFOFX>Il1cdhL?f(=C9rsiCc-#{9U7yZTlgWAwoq#CDr`82pnFM-DHH4{*uj^ zM;1j*hsE2v(`tP~wJ2-CJyww0a>RwpR#7D1mo7KK(*RPmddf?RPvVsMMfqovZ=+#5 zDwjW*n{bYpf8OK2;=W1=RDDgz7Q!adCiYCkiEbvja#!V_8!rE-5M3-iL%kb3AEIX} zW@0=18jY4#OIif{LhfptDXRNzRX-$?Ow7R{_IG|soMwUSF9Y)>qmH36O4p%Wqoti- z&(>C6J;K)+J>`YZ-iq9`u(ZWg`zf*9JDtiaC9x$~MI5qPEGHWJZX3Yqi-YHbF=kqm z(Toc_3Xk1HjluG8jj`GalZmVqUP^=U@#gqu4o4rL1D&SAwTjvAOA;-5cf}VXMd~S133C97SKLXW8cR zdvW4O_z0vHpnR-jTjM?Th=d1;2eLw3Rj(a#QaUJ+P|9UiS zJ+w6b-2GT!(QqO5*+@YgV88)9|ioCFw5Uw4~A=^t&dh zy3vVnp=jZ5bN*V-_Bd*B&C}O8dpCQm>n3PFNYWx^(Y#*AIrnG7PhO| zx?sMQJncQI-Bx~l#dx0Y12O8HR2o-4tX|RDynDQSe9Y&@seDrd_=lR9fS;Sd0P2(h`{&D|IAxp& zw+OkM9k-0_j%d8nODtYS?CejU{7W(23xirh!{Frv z12Ws&8w&x^xPW_-qobph$@x2DJn36DfJ~fBR4Z!p^)eHj#V{ z{3(8v_th_0(ydV)3pro%-cKKi#_AF#GBN;~cNrD{1%?WMc$dK5ZvYrB0O~Ip0FVU3 z`?stJM)kK1H~>;~_C~a0O!WZ5>R3j2s*s zKn5lt6BFIL1)Zb2jg!6`osA>uznuJUKf=b2h7RU-PUf~YM1TD18`wHK@sN=G3H0yl zU*j}(GyhK{8^^!XdQTAeM+0P}X8`_BG$(VD{|oJp=3lhG^7>ae?mx~r<;~rUt<;6h zt>35meQ3PQtSsDrh50`;{~74Nm@1CO4nnrp??flw|E$&D5Wn_8J?l00m(f?+s|BsA+qW{g1 zb1;9O2K_%n<7NCi!auRU?YV(}R{kHA@UJra3w^IMUU+WcziXBkJ}j@D1pvTik`NY9 zb^|-fa1URZbsm^FeoFJ|-+~Ia4z~t}9{7rg4F(2Jl2f4xPa%UQURJ1bB_>gzZ2e}Z zTtK5NlNRc;sH`v>%SH#AAh}LqtY^^K#IDQG&vxsU=H*js`{H?awsJ5r!MydO`ZBW# zYxU{H+m+*Pxpu{I{N+Jrd<&SK+#nAQ1rAjc3*M{|;>^z}PbA-|KtyGS9Ki2KTgWfJ zPHUpe&m;eiMEm{!gz#yJM>8YkZiuz*63doLu#ASFIN)}BX)eO02W<#E?JdkC9kcPi zk*AUQgPHySmm@~m@{}1D90X@qPfpu{RC=KoiHTohzdsSU3P*C2_nHdguIsWr1zdzEnkPb)wrI+!YX zMIy4}p86)Qk+#Xnz-vv{6PGA7z*NUEzWn2Bo{?z3P`93Lv=@q)M*LyyZE79I_05OK%Q(eSBWpo%}u78tx|jeviE=hw^2J-%bz6c zn4os=?rve~HROuTcQXue@A0Rghm(>&&y8rA*CeyeT6@J*Dp%l1CEtEE#-wzhEpg}^ zF|W3k-Zo+{B{o6IFB00pGh3UgB&55gH+&gQWBt?bm)^v79Wx9}ntt_e%^pzd%V6ct zQM~&#nHzAlKKc0%cGd8OD_$xEUe1OYJU6u;EhTF51_gWU7EU9n&HpGOtfc>*18mGx zU%U1`#026}vQIC2S}JAes45vP@f}w~WRTABG7Wumv=Sj%^S(K>c+!bqr=FW*!=6&D zQh_9G2Q}~Sac13M2!!;=CpDjER%YEZjDGYO7=}NhgkHE4XjB=Nhp71AjbyNJ6<}66 z3S(Iq#Tmk@4Y?MTiNME4KMlgE>?BDJ{;VJG>&y<-_p6ZVfiZk#YSqTa;|#UM)wr4G zLN|$S;4!ROk(W_d8U?Xg_W+ce{004pl2}EX%2oR=19l*Iln?fLP-R;;QCDTF6H|ID z?_Q1_147=hn5@LLn#&8v0OJ_jVq*$pWrPkrGL~kZIm0j`*? zbMV)Cn(M4w`xxmI=qRXJt@)IV-MU0*emHXAfav#J;4$%7wQ4+DtsZQ5@QSeZXdAOg z7Q3=fiSssq;Ek#)77Lb|#7Wjgo2tZvaN8EnaAtzOOB& zdY&br282&p{Djl7bzOxvs2^ZO=a}Ss_6B~{Ff!a(fQ{61412!H$+2zlwy?V;Uf^s_ zAjM$RxX#w$T|D7E{uB6l#1WeRvG7I>qWHtl)=-3RXQ?z=vdNPoyaJMi$?jfWIb)(7 zni_e(Ln&l2Zlb}^d`>%ByAuUI_k*ds09 zaIa&_+CRQ7|A0~G`6hXA=P|FGvWRpO{+mup>cr@+sor2ABPP!W!|N1s&fseZ(!fu# z6Kl7^hgmWBc725q=i1wkY(Id%T&cZ8lDsB;DDQ`&O@xMUp)fgaLXyXADB<$OHOQ$H ze=*XQl;1Fbw>w*Rvk|io{1h!WH0#Dpz*q>x8@67l2J^Vh^OnlqZ)12`-7$7S>h`Ge zT98EwZ*jYe`B2|*FW=Gji`%RWC0zsqO18LQFr?ewxNZTXBozOxp&sE9$v_vkX>&@-N2`@c3M&)5S;^GCVx_> zb4~E{eP2B@Kt3E)7AVB|S&|pu8pyFG^wqU7YJp|q0hxWs`RHf!!QFD#EAz7V7xQDO zVXpDi1g`tXe$Aq27{5ySeW|0;V@||5q-=i|QLJ44k)X;l`~H1~=h)m8PxoePUp61V zJ^3Fw8Y7D%ohlnsoclZhQ@qPb5Ck+Q7;et^k3&bAN@!ibG>x|NgIvo?t7Nb{e3oa8 zC0s5Q&Re`hekkcuTcA9%&weqv!LACbtgJT<@%DhmDFFy{8ae%0BH|XJ*OC}&Q<0ld z(c|(19Vsa*4d_yTfN!j z3)L7)?c*P>k)Av%;J`SB?#0y97GCCO7HnMFY}= zeIei;n7|A*OSDNt#6RdnB-+~wrreqNmX{1~$f-UIFZsuKp}M-kV`;cY^@+h- zEoI2ueh5E^J9Ao?9)LcvZD3iKkXgt&-mi0Rnp6o-$SpOK*6_}>hDz)%@A%d@UAPg$ zodMbZGGSv~SNZF0jNctt5_f+#soGqCcEOgW z84X74W}W+W#8!AS&-B$|vd>74Ds(J^?SY>@RavZK`8h&(ty$t#!`OpW7SmKEJv=$N z`7*=9YmR5nFgAh@=$^|Eo!3$`=w$dZMf7OtcUJ6WuboVu@fCF9rmG4k*({&w{cP=} zUO>YppsoyiGkUv#!{IZ z89W-N!Zj8zPSs8>S`+nMb=agiY37n*D~Kn6-~k8J^}Zd)B3<_oc#u^!IlwtXlAI11 z9}?gckZdZ-F`Qdgo&GCGnXu0*uBy)BYxX~fu$HH|*WAuYC9 zmK`&>G z$(#A|i`+f7{TlFZzeX1?tyBtPLuoh~FtzQS$`x~9R!2y92jCFmiQ;n&%BY%d&ksAI zJ}zR5YB0KDwd9-|HR%)LbGws%FJX{e?L^&G9whq_(W9sDjGh8-l!K@vfEpcB z8ia7Akm?$$Z_){$EzT%D_(UX^LL=QbY}}aCs|^nlqRE6U<58oGfDTRyl?nbR%+)rDDaFL8y{su)VMP z6KIxf_%PJ2Hl(&%or$wOSeH|N3;sZ<&@W3zN$x~cJ>_TtZv&6VI8cu9A0@4Zi1ww~SNS&e z;!)Hhdkib=nNeeLk!KYMVAdavcav%(QbHDgtA`XGlSVeg3c*1+pf(R`harc~ZBQQx z;mi?7dr<{w%fpqrn3Jb~Y-syMQfnZNf6kwqOw9A?9chnJV9UXp5Y|F?2i0zGH5uSx zCgG;#e)jf{2KQdftz9|tZM&PvegPnT#m$=@eC8z75t-w1Sjua9HrO@5IaRkH1RV@m z3mJ8OmKkQ~z_l8GFl`x_XDQ?~rnTRMC($FVp zqqb!bcq2Ky!3l&p8rt>Q3gnE8ygU{j-iqEMn@`9Y@39atw;hP)?MLABpFz;W=t`O_ z{G{@uLWm;!!2JCzp)W$uJYrV`I2vD6izSQBVeh_(bAUT=dZNUtN{qLkMs?NI$YsdYmG-VSl1k=qM>nb*K^S0 zVprOUx)SVd*-WDge2eNr$LdBC#|JrY57TlF&{AbZ|*a7WGXcYU9 z*%1$#?w=rj>k;>yji>%*OlXmJIAdh$<-yh_&r99tV{*BZF*@L*c%tvy^-+s|=Av6J zIcJ$n|9~B)7KvmZ&u$%Mk4_0J`k+pit~qF6t)pjcz0K_s4KWqQj*FI50{iV+MyZ!i zCVHdK0}Usv@V-#G9F-eY8AC_$*=gccN*WZ%0Yn)&khVPvsQ;q3LvZLZr`p1nF@TA+{Tr8QRwCd?W!x{}-lD%o%I?+9vF(KN=?UL3 zKHGu4fZ~pQ$V*AO#ARdu=toN>P)tF0bN}#*TgOuiehG`Ct_B?MaA8N(=gK4%r)B44 z9qE?pU4>j4-EHi6-?ExtnvJ_5Sa3Px>^rGGQMEIb7lpHgYwd%JIU)#0F^WJ_O6AL= zHFuF4QkNs9uZ*)C2X~yrV&q#pEAdRCflBP?%gq5r%H+5qqppxxS{#Ljk#pt z*Lh9K)G5e9FkQIJ#=jh$(t8M3sh35r_6B{v=%--#D90=p@(8B)ObaLff!5b}tpru8Mfg#5IO z0z}YFJ}q?ybZA%W``Fc?=Kv0xN8oxA<%k-s<&6AD=1XXA@`R|N-t1xEbO&2`nX|l@ zb6x2c=@(>oIB@a|nG-6BE+-`(1V@H+VS-(A5U?yYz%IH08%i>N)7u$P4_=#@p^LMR zudC@DMp|-$9YK%EJ#7S%&FhprugkUL^hjWOB7sVQ#%f!b8j#)k5NJD(p}Z`c1R2vP zR}&W@499O=m;e*4`2N%W6Bq0U8V2a>o&NMV?@Py=>N(EhdIQ)M+%65mCGGBlEoxRr$1bAhlB9`v}ZYNGP-Q zwCK8+5i(1Gg#8)K=-UsSrCg0lz;HAjKKb|w^&--vY82eU5EY{0o?o_xLTc}2N%YgO z&GEs^Ae;~LI&vxHqkU6T!?7|hC~#Wja&{u#4ao^*zHUg`6pFO3z=V>=UkYkb4XSdF zcPdD8tWB_zk{jI@L2p|j^{o5Y7Ey2?S%TlHc$jdmz$8U~N`fqyxQvo8_ep4Jti&}V z0a5XomV1xp6WI~bjG{Vs% z<+&?rFUH}|-)8c+QIAFBjN)6k z>v4NU3{wc7hr=Wx6lFpqM@aKhmJe3P{40ws1XtCRqK=GhQAtv8TDI=wqUG=cM{p$9rIz@geJ) z*PO`Y(?n6$Q6A7sai?`R{N`?JS8K_N;iXBsWw5 zA0HClh!N^LxGCcm_@Un)1o8hB5(A#KMd$*<1O@*d5gSU8b7X?;Vu|G0>9y|l{tzf0 zbK?*9h!c-MhsAX&xYwNgir}}@{58Go#o+w4&JYu|=tltS{Lf9t-m|^Kvm;=BC1LGX zH77R8D8dv$y(Yq1Ji#i|8$Nu`7%@haz7^WrbCl+XJklvA*oTk^gW|UDClke^S<#pO3rPXcLB9&}xKWtWCG2obDEayD z4B!)cF0DQ=^nCKP+wyX%+`Nzs!m1ZtJJ|Bn(>v35cRMgNE$c|;-Rqv+LJK-M+p@m! zSOXnd-5fZ-YN%nzA*?*Ht(1+<4a`5;dxv*q%C$V+Zw@?^RYvJ~rFE2!tvy+`cG%84 z)2BY!|17<~*ZQ3nn2VD-06+`u%?a D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restdownloads.md b/restapi_versioned_docs/version-REST API 2.23.0/restdownloads.md new file mode 100644 index 0000000..653b02c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restendpoints.md b/restapi_versioned_docs/version-REST API 2.23.0/restendpoints.md new file mode 100644 index 0000000..163cdf3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restendpoints.md @@ -0,0 +1,746 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", + "terminal_type": "PAXA920" + } + ] +``` + +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + + +:::caution +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restintroduction.md b/restapi_versioned_docs/version-REST API 2.23.0/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restobjects.md b/restapi_versioned_docs/version-REST API 2.23.0/restobjects.md new file mode 100644 index 0000000..8579f4b --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restobjects.md @@ -0,0 +1,825 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.23.0/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.23.0/restreleasenotes.md new file mode 100644 index 0000000..01faf55 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restreleasenotes.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 2.23.0 +**Bug fixes:** + +Support for MOTO operations in the Get Transaction Status service has been added + +## 2.22.4 +**Bug fixes:** + +Internal performance issues have been solved. + +## 2.22.3 +**Bug fixes:** + +A external vulnerability has been addressed. + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.23.0/restsandbox.md b/restapi_versioned_docs/version-REST API 2.23.0/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.0/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.22.3-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.22.3-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.22.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versioned_sidebars/version-REST API 2.22.4-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.22.4-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.22.4-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versioned_sidebars/version-REST API 2.23.0-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.23.0-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.23.0-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index c38a928..61c455f 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,7 @@ [ + "REST API 2.23.0", + "REST API 2.22.4", + "REST API 2.22.3", "REST API 2.22.2", "REST API 2.20.0", "REST API 2.17.0", From b1724bc84b512636f3feefb401df64e6155e536e Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Thu, 30 Oct 2025 11:40:42 +0100 Subject: [PATCH 113/115] improv: Android SDK 7.1010.6 release notes have been complemented (#150) --- .../version-Android SDK 7.1010.6/androidreleasenotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md index 4d22296..05dcb56 100644 --- a/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md +++ b/android_versioned_docs/version-Android SDK 7.1010.6/androidreleasenotes.md @@ -15,7 +15,7 @@ Don’t miss any updates on our latest releases. Contact your Handpoint relation ## 7.1010.6 **Features**: -- Partial reversals are supported now +- `Partial Voids` (also known as Partial Reversals) are now supported for *TSYS* acquirer. Please see [Handling Partial Voids with TSYS](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5210701825/Handling+Partial+Voids+with+TSYS) for further information on this. - Support for PAX A3700 reader has been added From ba8efaa9df83c07aad884fecf080d3bfc02e4994 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Fri, 14 Nov 2025 12:23:33 +0100 Subject: [PATCH 114/115] SDK-4014 (#151) * feat: Adding Android SDK 7.1010.7 release notes * feat: Adding REST API 2.23.1 documentation * feat: Adding Javascript SDK 7.2.4 documentation * fixing broken link --- android/androidreleasenotes.md | 6 + .../androidapioverview.md | 22 + .../androiddevicemanagement.md | 417 ++++ .../androideventlisteners.md | 731 ++++++ .../androideventsubscribers.md | 73 + .../androidintegrationguide.md | 820 +++++++ .../androidintroduction.md | 138 ++ .../androidmigrationguide.md | 265 +++ .../androidobjects.md | 1216 ++++++++++ .../androidreleasenotes.md | 481 ++++ .../androidtransactions.md | 2028 +++++++++++++++++ ...version-Android SDK 7.1010.7-sidebars.json | 8 + android_versions.json | 1 + .../javascriptintroduction.md | 39 + .../javascriptobjects.md | 758 ++++++ .../javascriptprocessingpayments.md | 23 + .../javascriptquickintegration.md | 112 + .../javascriptreleasenotes.md | 104 + .../javascriptsandbox.md | 45 + .../javascriptterminalmanagement.md | 262 +++ .../javascripttransactiontypes.md | 779 +++++++ ...version-JavaScript SDK 7.2.4-sidebars.json | 8 + javascript_versions.json | 1 + restapi/restobjects.md | 3 +- restapi/restreleasenotes.md | 5 + .../assets/postmanCollection.png | Bin 0 -> 10363 bytes .../version-REST API 2.23.1/restdownloads.md | 10 + .../version-REST API 2.23.1/restendpoints.md | 746 ++++++ .../restintroduction.md | 55 + .../version-REST API 2.23.1/restobjects.md | 826 +++++++ .../restprocessingpayments.md | 22 + .../restreleasenotes.md | 127 ++ .../version-REST API 2.23.1/restsandbox.md | 44 + .../version-REST API 2.23.1-sidebars.json | 8 + restapi_versions.json | 1 + 35 files changed, 10183 insertions(+), 1 deletion(-) create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidapioverview.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androiddevicemanagement.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androideventlisteners.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androideventsubscribers.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidintegrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidintroduction.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidmigrationguide.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidobjects.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidreleasenotes.md create mode 100644 android_versioned_docs/version-Android SDK 7.1010.7/androidtransactions.md create mode 100644 android_versioned_sidebars/version-Android SDK 7.1010.7-sidebars.json create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptintroduction.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptobjects.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptprocessingpayments.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptquickintegration.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptreleasenotes.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptsandbox.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptterminalmanagement.md create mode 100644 javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascripttransactiontypes.md create mode 100644 javascript_versioned_sidebars/version-JavaScript SDK 7.2.4-sidebars.json create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/assets/postmanCollection.png create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restdownloads.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restendpoints.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restintroduction.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restobjects.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restprocessingpayments.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restreleasenotes.md create mode 100644 restapi_versioned_docs/version-REST API 2.23.1/restsandbox.md create mode 100644 restapi_versioned_sidebars/version-REST API 2.23.1-sidebars.json diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 4d22296..9fda179 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -12,6 +12,12 @@ Don’t miss any updates on our latest releases. Contact your Handpoint relation ::: +## 7.1010.7 +**Fixes** + +- Deprecated coroutines APIs have been removed to improve compatibility for integrators + + ## 7.1010.6 **Features**: diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.7/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.7/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.7/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidintegrationguide.md new file mode 100644 index 0000000..d9114a4 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidintegrationguide.md @@ -0,0 +1,820 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the **release candidates 7.xxxx.xx-RC** SDK. +- If you are integrating your software with a **PAX production terminal** you will need to get the **production** SDK. +- If you are integrating your software with an **HiLite terminal** you will need to get the **production** SDK. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidintroduction.md new file mode 100644 index 0000000..5e2a9ce --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidintroduction.md @@ -0,0 +1,138 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.3-RC.1-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.3** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidreleasenotes.md new file mode 100644 index 0000000..9fda179 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidreleasenotes.md @@ -0,0 +1,481 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + + +## 7.1010.7 +**Fixes** + +- Deprecated coroutines APIs have been removed to improve compatibility for integrators + + +## 7.1010.6 +**Features**: + +- Partial reversals are supported now + +- Support for PAX A3700 reader has been added + +**Fixes** + +- Processing misalignment between SDK and Gateway has been fixed + + +## 7.1010.5 +**Features**: + +A new `cardPresent` flag is supported in Integrated mode, which comes from our [REST API](/restapi/restintroduction) or its related Cloud clients [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). This new flag allows to indicate the payments flow that a Reversal operation will imply an actual present card. Please see [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for further information on the purpose of this flag. + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.7/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.7/androidtransactions.md new file mode 100644 index 0000000..7df8589 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.7/androidtransactions.md @@ -0,0 +1,2028 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.7-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.7-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.7-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 6106d32..3761e1e 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.7", "Android SDK 7.1010.6", "Android SDK 7.1010.5", "Android SDK 7.1010.3", diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptintroduction.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptintroduction.md new file mode 100644 index 0000000..3b63fd1 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptintroduction.md @@ -0,0 +1,39 @@ +--- +sidebar_position: 1 +id: javascriptintroduction +--- + + + +# Introduction {#javascriptIntro} + +
+
+
+

JavaScript SDK

+
+
+ + + +
+ +
+
+ +

+ +Download the Handpoint JavaScript SDK to integrate leading smartpos terminals with your cloud based software. The Handpoint JavaScript SDK is a simple javascript interface running in your web application which acts as a bridge between **the web browser and the payment terminal**, while shielding your software from handling card data. It is seamless to integrate, keeps your software out of PCI scope, and allows you to use the best Android terminals on the market. + +Complete your integration in just three steps, initialize the interface, choose a terminal and start a sale. It is as simple as it sounds. The only thing you need is a valid API key to communicate with the payment terminal. As part of the initialize step you will get back a list of terminals with which you can connect. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipt in your software, all while you monitor the transaction status. The Handpoint Javascript SDK seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +For your merchants, the terminal setup is easier than a standalone. A merchant connects the terminal to their network, just like a smartphone, authenticates his/her account, and it simply works. Your software then control the terminal from anywhere in the world, and your merchants have secure, reliable and intuitive payments. + +## API Overview + +The following transaction flow shows how easy it is to add card present payments to your web based application. The interaction between your cloud application and the Handpoint Javascript SDK is simple and streamlined. The Handpoint Javascript SDK takes care of the communication with the payment terminal. The status messages are received in your web application via the callback function defined in the financial operation requests call. That’s it. + +![Sandbox logo](/img/jsoverview.png) + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptobjects.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptobjects.md new file mode 100644 index 0000000..bd8432b --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptobjects.md @@ -0,0 +1,758 @@ +--- +sidebar_position: 8 +id: javascriptobjects +--- + + +# Objects + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing the supported acquirers for merchant authentication + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + +Balance available on the card. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance amount.| +| `currency`
*Currency* | The balance currency.| +| `positive`
*Boolean* | Marks if the balance is positive.| +| `negative`
*Boolean* | Marks if the balance is negative.| + +**Code example** + +```json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +``` + +## Bypass Options{#19} + +`BypassOptions` Object + +Configuration to enable/disable signature or pin bypass. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Bypasses PIN entry when the cardholder does not know the PIN of the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN bypass should be set to true in order for the cardholder to be able to bypass the PIN by clicking once on the "validate(green)" button of the PIN screen on the payment terminal.| +| `signatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature for US merchants, they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature.| + +**Code example** + +```json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +``` + +## Card Entry Type{#29} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name{#30} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency{#31} + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + + +## Device{#20} + +`Device` Object + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Device shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal type.| +| `device_name` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type"| + +**Code example** + +```json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920", + "device_name": "0821032395-PAXA920" +} +``` + +## Device Status{#27} + +`DeviceStatus` Object + +A class which holds the payment terminal status. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String * | The serial number of the payment terminal.| +| `BatteryStatus`
*String * | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String * | The battery millivolts of the payment terminal.| +| `BatteryCharging`
*String * | The battery charging status of the payment terminal.| +| `ExternalPower`
*String * | The external power status of the payment terminal.| +| `ApplicationName`
*String * | The application name used by the payment terminal.| +| `ApplicationVersion`
*String * | The application version number used by the payment terminal.| +| `bluetoothName`
*String * | The bluetooth interface name used by the payment terminal.| +| `statusMessage`
*String * | Status message of the payment terminal.| + +**Code example** + +```json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +``` + +## Financial Status{#33} + +`FinancialStatus` Enum + +An enum representing different statuses for a completed transaction. + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](javascripttransactiontypes.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](javascriptterminalmanagement.md#17) method. + + +## Merchant Auth{#17} + +`MerchantAuth` Object + +An object used to store merchant authentication. This object can be empty, it allows a transaction to be funded to a specific merchant account other than the default one (linked to the API key). It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#28) | Array of credentials.| + +**Code example** + +```json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +``` + +## Merchant Auth Credential{#28} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#21) | If present, it links the credential to a specific acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials.| + + +**Code example** + +```json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +``` + +## Merchant Auth Options{#25} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], +} +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient.(**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + + + +## Operation Start Result + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `transactionResult`
*String* | Promise that will resolve/reject with [Transaction Result](javascriptobjects.md#18) object. | + + +## Options{#26} + +`Options` Object + +An object to store all the customisation options for an operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + +## Payment Scenario{#34} + +`PaymentScenario` Enum + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Refund Options{#24} + +`RefundOptions` Object + +An object to store the customization options for a refund. This object can be empty if no options are required. + +**Code example** + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable tokenization in the payments flow. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Sale Options{#23} + +`SaleOptions` Object + +An object to store the customization options for a sale operation. This object can be empty if no options are required. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `customerReference`
*String* | An arbitrary string to use as your own identifier for a transaction.| +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `duplicate_check`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `TipConfiguration`
[*TipConfiguration*](#39) | Configuration for the tipping menu of the payment terminal.| +| `bypassOptions`
[*BypassOptions*](#19) | Configuration required to bypass the pin or signature verification methods.| +| `merchantAuth`
[*MerchantAuth*](#17) | Configuration required to fund a specific merchant account in a multi-mid scenario (one payment terminal funding multiple merchants).| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](javascriptobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```json +{ + "customerReference": "MyCustomReference", + "tokenize": false, + "duplicate_check": false, + "tipConfiguration": { + "baseAmount": "100", + "skipEnabled": true, + "enterAmountEnabled": true, + "tipPercentages": [ + 1, + 2, + 3, + 5 + ] + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [ + { + "acquirer": "ACQUIRER", + "mid": "11111", + "tid": "22222", + "mcc": "33333" + } + ], + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Status{#38} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*bool* | A `boolean` allowing the user to know if the payment terminal will accept a cancel request.| +| `status`
[*status*](#38) | A `status` enum representing the status of the transaction.| +| `message`
*String* | A `string` containing the status message of the transaction.| +| `deviceStatus`
[*Device Status*](#27) | A `DeviceStatus` object containing information about the payment terminal.| + + +## Tender Type{#35} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +An object holding information about the configuration of the tipping menu for the payment terminal. When a tipping configuration is sent to the payment terminal, the card reader will prompt the cardholder with a tipping menu at the time of the transaction with the parameters that have been sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + baseAmount: '2000', + tipPercentages: [5,10,15,20,25], + enterAmountEnabled: true, + skipEnabled: false, + footer: 'Thank you!!! ;)' +} +``` +## Transaction Result Object{#18} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `batchNumber`
*String * | If available from the acquirer, the batch number where this transaction has been included| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#29) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#30) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#31) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#27) | Status of the payment terminal| +| `dueAmount`
*Number* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*Date (Unix epoch)* | Time of the transaction (based on the date and time of the payment terminal) | +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#33) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#34) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#35) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#36) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#37) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| + +**Code example** + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +## Transaction Status{#22} + +`TransactionStatus` Object + +A class which holds the payment terminal status. This object is received in the financial operation callback. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `deviceStatus`
[*Device Status*](#27) | OPTIONAL - The status of the payment terminal.| +| `isCancelAllowed`
*boolean* | Defines if the transaction can be cancelled or not.| +| `message`
*String* | Human readable status message.| +| `status`
[*status*](#38) | An enum containing information about the status of the transaction.| + + +## Transaction Type{#36} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` `SALE_AND_TOKENIZE_CARD` `UPDATE` `PRINT_RECEIPT` + + +## Verification Method{#37} + +`VerificationMethod` Enum + +An enum representing different cardholder verification methods. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + + diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptprocessingpayments.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptprocessingpayments.md new file mode 100644 index 0000000..e12bddd --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptprocessingpayments.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 3 +id: javascriptprocessingpayments +--- + + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptquickintegration.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptquickintegration.md new file mode 100644 index 0000000..f5c935d --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptquickintegration.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 4 +id: javascriptquickintegration +--- + + + +# Integration Guide + +:::tip +Pre-requisite: request your test credentials (API key) and test payment terminal from Handpoint. +::: + +The following example shows how you can integrate your web application with the Handpoint javascript SDK to perform a sale transaction in four easy steps: + +1) Download the [handpoint.js](javascriptintroduction.md#javascriptIntro) SDK. + +2) In the same directory, copy both handpoint.js and the code below in an html file. + +3) In the code below, replace the variable apiKey with your test api key and replace the variable deviceName with the concatenation of your terminal serial number and model, for example **0821032395-PAXA920**. + + Note: If your payment terminal shows the debug watermark on the screen when it is on, then keep the variable `environmentIsDevelopment` to true otherwise change it to false. + +4) Open the HTML file in the browser and see the test transaction immediately. + +**SIMPLE, FAST, and EASY** + +```html + + + + + Handpoint SDK Trial Integration + + + + + + + + + +``` + +:::tip +Maintain the connection with the terminal at all times: +- To be able to recover a transaction result through the callback passed in the [*init*](javascriptterminalmanagement.md#1) method, the point of sale and the terminal **MUST** be connected and online. For that reason, we recommend to connect to the target terminal and maintain the connection alive at all times instead of connecting and disconnecting for every transaction. +- Using the same connection, the user may perform as many transactions as desired. The SDK is in charge of maintaining the secure channel between the point of sale and the terminal. No connection and disconnection between transactions is required. The silent connected periods will provide the possibility for the device to deliver any pending transaction result in case of a network issue. + +How Transaction Recovery Works: +- The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the Point of sale in case it becomes unreachable (network issue or other). For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the point of sale is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). The recovery loop is reinitialized every time the Handpoint application is restarted or anytime the startRecovery method is used. +::: \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptreleasenotes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptreleasenotes.md new file mode 100644 index 0000000..f782033 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptreleasenotes.md @@ -0,0 +1,104 @@ +--- +sidebar_position: 2 +id: javascriptreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 7.2.4 +**Features:** + +The batch number is returned in the Transaction Result object now as `batchNumber`, provided the acquirer returns it. Please see [Transaction Result Object](javascriptobjects.md#18) + +## 7.2.3 +**Features:** + +A new `cardPresent` parameter is available under [ReversalOptions](javascriptobjects.md#40). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 7.2.2 +**Features:** + +A new `tokenize` parameter is available under [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 7.2.0 +**Features:** + +We're excited to announce the latest update to our JavaScript SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](javascriptobjects.md#money-remittance-options)), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 7.1.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](javascripttransactiontypes#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](javascripttransactiontypes#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](javascripttransactiontypes#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](javascripttransactiontypes#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +## 7.0.0 +**BREAKING CHANGE:** + +We are introducing a new feature called [Get Transaction Status](javascriptterminalmanagement.md#17). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](javascriptobjects.md#operation-start-result) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + + +When starting a new financial operation (sale, refund etc.) the `OperationStartResult` object will contain two new attributes: +- `transactionReference`: This universally unique identifier (UUID v4) will allow you to query the Handpoint gateway directly to know the outcome of the transaction. This feature is to be used in case there is a connection issue or any other problem preventing the terminal from delivering the end of transaction to your software. +- `transactionResult`: Promise that will resolve/reject with the [Transaction Result](javascriptobjects.md#18) object. + +## 6.3.0 + +**Features**: + +We are introducing a new feature called [Transaction Metadata](javascriptobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.1 + +**Fixes**: +- Reconnection management. + +## 6.2.0 + +**Features**: + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. You do not need to update to v6.2.0 to benefit from this new feature. v6.2.0 will only allow you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [SaleOptions](javascriptobjects.md#23) and [RefundOptions](javascriptobjects.md#24). + +## 6.1.0 + +**Features**: +- Mail order/Telephone order (MoTo) + +**Fixes**: +- Duplications on recovered transactions + +## 6.0.1 + +**Features**: +- Internal variable handling + +## 6.0.0 + +**BREAKING CHANGE:** +- The recovery function in the init method was added to make sure that ALL transaction results are received by the POS, even in case of an unstable network connection. The recovery function passed as third parameter in the init method MUST return a promise. The resolution of the promise will send a message to the payment terminal acknowledging the reception of the transaction result. diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptsandbox.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptsandbox.md new file mode 100644 index 0000000..576ac23 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptsandbox.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 5 +id: javascriptsandbox +--- + + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptterminalmanagement.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptterminalmanagement.md new file mode 100644 index 0000000..9a7c809 --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascriptterminalmanagement.md @@ -0,0 +1,262 @@ +--- +sidebar_position: 7 +id: javascriptterminalmanagement +--- + + +# Terminal Management + +## Initialize{#1} + +`Initialize` Method + +Initializes the JavaScript SDK and returns the list of payment terminals associated with the account. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `API_key` Required
*string* | The API key provided by Handpoint for the merchant.| +| `dev_or_prod_environment` Required
*boolean* | Value which defines if the JS SDK is targeting the development environment (true -> cloud.handpoint.io) or the production environment (false -> cloud.handpoint.com).| +| `recovery_EoT_callback` Required
*promise* |Promise collecting the pending transaction results which couldn't be delivered to the web application during the execution of the transaction, for example if the network connection became unstable. The callback input parameter is a TransactionResult object. When the promise is resolved the JS SDK will send the ACK to the payment terminal to mark the result as recovered and the device will delete it from its storage. If the promise is rejected, the device will resend the TransactionResult until the promise is correctly resolved and the ACK sent to the payment terminal. The sdk has a 5 second window for the promise to be resolved | + +**Code example** + +```javascript +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return handleTransactionResultPromise(pendingEoT); +}) + +// For simple or sync operations you may return a resolved Promise. +Handpoint.init('API KEY', true, (pendingEoT) => { + console.log('Recovered Transaction -> ' + JSON.stringify(pendingEoT); + return Promise.resolve(); +}) +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Devices**| List of device objects.| + + +## Connect{#2} + +`Connect` Method + +Connects the Javascript SDK to a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to connect to. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('0821330373-PAXA920'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|**200** code for OK
**403** code for NOK| + + +## Disconnect{#3} + +`Disconnect` Method + +Disconnects the Javascript SDK from a payment terminal. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device_name` Required
*string* | The target payment terminal to disconnect from. The device_name is returned in the Device object of the initialize call.| + +**Code example** + +```javascript +Handpoint.connect('1850345672-PAXA920PRO'); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Connection Result**|`Disconnected` message for OK
`ERROR disconnecting` message for NOK| + + +## Stop Listening Device{#7} + +`StopListeningDevice` Method + +This operation stops the connection between your application and the payment terminal. It stops listening to transaction events and resets the connection with the card reader. + + +**Code example** + +```javascript +//Stop Listening to Events +Handpoint.stopListeningDevice(); +``` +## Stop Current Transaction{#13} + +`StopCurrentTransaction` Method + +Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. + + +**Code example** + +```javascript +Handpoint.stopCurrentTransaction(); + +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|`{finStatus: CANCELLED, statusMessage: 'Operation stopped'}`| +| **Promise Error Response**|`{finStatus: FAILED, errorMessage: 'Unable to stop current transaction'}`| +| **Promise Error Response**|`{ finStatus: FAILED, errorMessage: 'No response received from the card reader' }`| + + +## Print Receipt{#14} + +`PrintReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*string* | HTML receipt or url to locate the receipt, it can be found in the response of a financial operation, in the fields merchantReceipt or customerReceipt. The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format).| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.printReceipt('https://location_of_receipt_container.com/receipt_location', CallbackFunction(stat){...}); + +var htmlReceipt = '[...] HTML receipt [...]' + +Handpoint.printReceipt(htmlReceipt, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Print Receipt Response**|A specific status object which describes the printing action (PrinterOutOfPaper, ErrorConnectingToPrinter or ReceiptPrintSuccess)| + + +## Ping Device{#15} + +`PingDevice` Method + +This operation will ping the terminal to confirm if it is online. The promise is correctly resolved if the device is online and successfully answers to the ping + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + + +**Code example** + +```javascript +Handpoint.pingDevice(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Device Status**|A [*Device Status*](javascriptobjects.md#27) object.| + +## Update{#16} + +`Update` Method + +Triggers a terminal software and config update. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +Handpoint.update(CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Update Response**|A financial response object.| + + + +## Get Transaction Status{#17} + +`getTransactionStatus` Method + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object. + + +The main [*FinancialStatus*](javascriptobjects.md#33) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](javascriptobjects.md#operation-start-result) object.| + +**Code example** + +```javascript +Handpoint.getTransactionStatus(transactionReference).then( + transactionResult => { + console.log('Transaction Result -> ' + JSON.stringify(transactionResult)) + } +).catch( + errorStatus => console.log('ERROR in getTransactionStatus -> ' + JSON.stringify(errorStatus)) +); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Transaction Status**| A [*Transaction Result*](javascriptobjects.md#18) object, indicating the status of the requested transaction.| \ No newline at end of file diff --git a/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascripttransactiontypes.md b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascripttransactiontypes.md new file mode 100644 index 0000000..928fddc --- /dev/null +++ b/javascript_versioned_docs/version-JavaScript SDK 7.2.4/javascripttransactiontypes.md @@ -0,0 +1,779 @@ +--- +sidebar_position: 6 +id: javascripttransactiontypes +--- + +# Transaction Types + +## Sale{#4} + +`Sale` Method + +A sale initiates a transaction with the payment terminal. In its simplest form, you only have to pass the amount and currency as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale ([Tip Configuration](javascriptobjects.md#39), [Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + metadata: { + metadata1: "data1", + metadata2: "data2", + metadata3: "data3", + metadata4: "data4", + metadata5: "data5" + }, + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.sale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## Sale And Tokenization{#5} + +`SaleAndTokenization` Method + +A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions` Required
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a sale and tokenize ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + tipConfiguration: { + baseAmount: "100", + skipEnabled: true, + enterAmountEnabled: true, + tipPercentages: [ + 1, + 2, + 3, + 5 + ] + }, + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.saleAndTokenization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Transaction Recovery{#6} + +`StartRecovery` Method + +The terminal has a transaction recovery loop to automatically send back the pending [*Transaction Result*](javascriptobjects.md#18) to the web application in case it becomes unreachable (network issue or other). + +For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the web application is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + +The recovery loop is reinitialized every time the Handpoint application is restarted on the payment terminal or the startRecovery method is triggered.The [*Transaction Result*](javascriptobjects.md#18) received through the transaction recovery loop will have the recoveredTransaction field set to true. + +**Important information: The web application must be successfully connected to a terminal in order to receive the pending transactions.** + +**Code example** + +```javascript +//Start recovery of pending transactions +Handpoint.startRecovery(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Promise Successful Response**|The event has been sent to the payment terminal.| +| **Promise Error Response**|The event was not sent to the payment terminal because it is unreachable.| + + +## Sale Reversal{#8} + +`SaleReversal` Method + +A sale Reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original sale authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a saleReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.saleReversal('1000', 'USD', 'OriginalSaleGUID', saleReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund{#9} + +`Refund` Method + +A refund initiates a transaction with the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. In its simplest form, you only have to pass the amount and currency as parameters. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | The transaction id of the original sale authorization.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund ([Metadata](javascriptobjects.md#metadata), [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + bypassOptions: { + signatureBypass: true, + pinBypass: true + }, + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.refund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult + +// Linked Refund +handpoint.refund('1000', 'USD', 'OriginalSaleGUID' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Refund Reversal{#10} + +`RefundReversal` Method + +A Refund Reversal, also called Refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In its simplest form, you only have to pass the amount, currency and originalTransactionID as parameters. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID` Required
*string* | The transaction id of the original refund authorization.| +| `merchantAuthOptions`
[*MerchantAuthOptions*](javascriptobjects.md#25) | An object to store the customization options for a refundReversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundReversalOptions = { + customerReference: "MyCustomReference", + merchantAuth: [ + { + acquirer: "ACQUIRER", + mid: "11111", + tid: "22222", + mcc: "33333" + } + ], +} + +let operationStartedResult = handpoint.refundReversal('1000', 'USD', 'OriginalRefundGUID', refundReversalOptions, CallbackFunction(stat){...}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Sale + +`moToSale` Method + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `saleOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a MOTO sale (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } + } + +let operationStartedResult = handpoint.moToSale('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Refund + +`moToRefund` Method + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `originalTransactionID`
*string* | If this field is populated, it links the refund with a previous sale and effectively limits the maximum amount refunded to that of the original transaction.| +| `refundOptions`
[*RefundOptions*](javascriptobjects.md#24) | An object to store the customization options for a refund (Customer reference, [Money Remittance Options](javascriptobjects.md#money-remittance-options),...). This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var refundOptions = { + customerReference: "MyCustomReference", + moneyRemittanceOptions:{ + fullName:"John Doe", + countryCode:"USA" + } +} + +let operationStartedResult = handpoint.moToRefund('1000', 'USD', undefined ,refundOptions, CallbackFunction(stat){...}); + +// Linked Refund +Handpoint.moToRefund('1000', 'USD', '00000000-0000-0000-0000-000000000000' ,refundOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## MoTo Reversal + +`moToReversal` Method + +A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*string* |The transaction id of the original sale or refund authorization.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO reversal operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var moToReversalOptions = { + customerReference: "MyCustomReference" +} + +let operationStartedResult = handpoint.moToReversal('00000000-0000-0000-0000-000000000000', moToReversalOptions, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + + +## MoTo Pre-Auth + +`moToPreAuthorization` Method + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*integer* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `currency` Required
*string* | Currency of the transaction.| +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a MOTO sale. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var saleOptions = { + customerReference: "MyCustomReference", + } + +let operationStartedResult = handpoint.moToPreAuthorization('1000', 'USD', saleOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +let transactionReference = operationStartedResult.transactionReference +let result = await operationStartedResult.transactionResult +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartedResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Specifically the `transactionReference` and the `transactionResult` (promise).| + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale or a pre-auth capture transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and WORLDPAY/VANTIV. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigInteger* |Tip amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `originalTransactionID` Required
*String* |Transaction id of the original transaction| + +**Code example** + +```javascript +handpoint.tipAdjustment('100', '00000000-0000-0000-0000-000000000000') { +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Status Message**| `Tip adjusted` message for OK
`ERROR` message for NOK| + + + +## Tokenize Card{#11} + +`TokenizeCard` Method + +Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a tokenizeCard operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Tokenize Card Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Card Pan{#12} + +`CardPan` Method + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*Options*](javascriptobjects.md#26) | An object to store the customization options for a cardPan operation. This object can be empty if no options are required.| +| `callback_function` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +var options = { + customerReference: "MyCustomReference", +} + +Handpoint.tokenizeCard(options, CallbackFunction(stat){...}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **Card Pan Response**|[*Transaction Result Object*](javascriptobjects.md#18)| + + +## Pre-Auth + + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `preauthOptions`
[*SaleOptions*](javascriptobjects.md#23) | An object to store the customization options for a pre-auth. This object can be empty if no options are required.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth operation +let operationStartedResult = handpoint.preAuthorization('1234', 'EUR', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +``` + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Increase operation +let operationStartedResult = handpoint.preAuthorizationIncrease('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); + +// Perform the PreAuth Decrease operation +let operationStartedResult = handpoint.preAuthorizationIncrease('-1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to be pre-authorized - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*Currency* | Currency of the pre-auth| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Capture operation +let operationStartedResult = handpoint.preAuthorizationCapture('1234', 'EUR','00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](javascripttransactiontypes.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](javascriptobjects.md#33) -> [AUTHORISED](javascriptobjects.md#33)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth transaction| +| `preauthOptions`
*Options* | An object to store merchant authentication options for pre-auth operations.| +| `callback_function ` Required
*string* | Callback function to subscribe to the transaction status updates.| + +**Code example** + +```javascript +// Perform the PreAuth Reversal operation +let operationStartedResult = handpoint.preAuthorizationReversal('00000000-0000-0000-0000-000000000000', preauthOptions, function (stat) { + console.log('Transaction status received -> '+ stat.message) +}); +``` + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](javascriptobjects.md#operation-started-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| diff --git a/javascript_versioned_sidebars/version-JavaScript SDK 7.2.4-sidebars.json b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.4-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/javascript_versioned_sidebars/version-JavaScript SDK 7.2.4-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/javascript_versions.json b/javascript_versions.json index 3c4fb77..4a9a8b1 100644 --- a/javascript_versions.json +++ b/javascript_versions.json @@ -1,4 +1,5 @@ [ + "JavaScript SDK 7.2.4", "JavaScript SDK 7.2.3", "JavaScript SDK 7.2.2", "JavaScript SDK 7.2.0", diff --git a/restapi/restobjects.md b/restapi/restobjects.md index 8579f4b..c6942dd 100644 --- a/restapi/restobjects.md +++ b/restapi/restobjects.md @@ -661,7 +661,7 @@ An object to store information about the request sent to the payment terminal. ```` -## Transaction Result Object +## Transaction Result Object {#transactionResult} `TransactionResult` Object @@ -682,6 +682,7 @@ An object holding information about the result of a transaction. | `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| | `authorisationCode`
*String * | Acquirer response code| | `balance`
[*Balance*](#balance) | Balance available on the card| +| `batchNumber`
*String * | If available from the acquirer, the batch number where this transaction has been included| | `budgetNumber`
*String * | Used to split payments over a period of months| | `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| | `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| diff --git a/restapi/restreleasenotes.md b/restapi/restreleasenotes.md index 01faf55..5b1b534 100644 --- a/restapi/restreleasenotes.md +++ b/restapi/restreleasenotes.md @@ -9,6 +9,11 @@ id: restreleasenotes Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: +## 2.23.1 +**Features:** + +The batch number is returned in the Transaction Result object now as `batchNumber`, provided the acquirer returns it. Please see [Transaction Result Object](restobjects.md#transactionResult) + ## 2.23.0 **Bug fixes:** diff --git a/restapi_versioned_docs/version-REST API 2.23.1/assets/postmanCollection.png b/restapi_versioned_docs/version-REST API 2.23.1/assets/postmanCollection.png new file mode 100644 index 0000000000000000000000000000000000000000..ec43e6ee9251285047dd64b4830de86a29183c72 GIT binary patch literal 10363 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 D2sD7D literal 0 HcmV?d00001 diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restdownloads.md b/restapi_versioned_docs/version-REST API 2.23.1/restdownloads.md new file mode 100644 index 0000000..653b02c --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restdownloads.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 4 +id: restapidownloads +--- + +# POSTMAN Collection + +Below is a Postman collection to get started with the REST API integration. In this collection you will find examples of different [operations](restobjects#operation-types-description) such as initialize, ping device, sale, sale (money remittance example), MOTO sale, sale and tokenize, sale reversal, sale with partial approval, refund, linked refund, refund reversal, print receipt(Bitmap and custom receipt), tokenize card, update terminal, tip-adjustment, Pre-Auth, MOTO Pre-Auth, [GetTransactionResult](restendpoints.md#transaction-resulttransactionresultid) and [GetTransactionStatus](restendpoints.md#transactionstransactionreferencestatus). + +[Download this Postman Collection](/files/API_REST_Nov2023.postman_collection.json.zip) diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restendpoints.md b/restapi_versioned_docs/version-REST API 2.23.1/restendpoints.md new file mode 100644 index 0000000..163cdf3 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restendpoints.md @@ -0,0 +1,746 @@ +--- +sidebar_position: 6 +id: restendpoints +--- + + + +# REST API Endpoints + + +## /initialize + + + +`Initialize` + +Initializes the REST API client and returns the list of payment terminals associated with the merchant account. We recommend that you display the list of available payment terminals to the merchant in your software. Each API key is unique per merchant and needs to be configurable in your backend. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | + + +Returns + + +| Devices | +| ----------- | +| List of [Device](restobjects.md#deviceObject) object. | + + +**Code Example** + + +```shell +Operation executed using CLI tool CURL: + +REQUEST: + curl -X GET \ + -H "ApiKeyCLoud: MeRcHaNt-ApIkEy" \ + "https://cloud.handpoint.com/initialize" (production) + "https://cloud.handpoint.io/initialize" (development) + +RESPONSE: + Code 200 -> Body: + [ + { + "merchant_id_alpha": "merchantID", + "serial_number": "082104578", + "ssk": "A1B2C3D4E5F60718293A4B5C6D7E8F901A2B3C4D5E6F7890ABCDEF0123456789", + "terminal_type": "PAXA920" + } + ] +``` + +:::tip +Reminder that SSK (Shared Secret Key) is a value unique to a Merchant, and the same Merchant (SSK) can have assigned multiple devices from different manufacturers. This includes PAX and Datecs (eg. HiLite) +::: + + + +## /transactions + + + +`Transactions` + +POST endpoint used to send a financial operation to the payment terminal. The transaction type to be executed (sale, refund etc.) is defined in the `operation` field of the request body. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Request Body: Transaction Request` Required
[TransactionRequest](restobjects.md#transactionRequest) | Object containing the transaction request information. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **Transaction Accepted** | The response code 202 is received from the API if the transaction was successfully sent to the payment terminal. | +| **BadRequest DeviceIsBusy Error** | The response code 400 with error 1001 is received from the API if the payment terminal is already processing a transaction. | +| **BadRequest DeviceNotResponding Error** | The response code 400 with error 1002 is received from the API if the payment terminal is offline. | +| **BadRequest CancelOperationNotAllowed Error** | The response code 400 with error 1003 is received from the API if the stopCurrentTransaction operation cannot be executed. A transaction can only be cancelled at specific steps of the transaction, while waiting for the card to be inserted or on PIN screen. | + +**Code Example** + +:::tip +Make sure that your transactionReference is unique per request, and change it for every new request attempt (even if the request contains the same values re-attempt). This will improve logs and could help troubleshooting. +::: + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X POST \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + -H"Content-Type: application/json" \\ +Transaction Request without callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ +Transaction Request with callbackUrl and token + -d '{ + "operation":"sale", + "amount":"10000", + "currency":"EUR", + "terminal_type":"PAXA920", + "serial_number":"1547854757", + "customerReference":"op15248", + "callbackUrl":"https://url.where.the.result.is.served.com", + "token":"123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f" + }' \\ + "https://cloud.handpoint.com/transactions" (production) + "https://cloud.handpoint.io/transactions" (development) + +RESPONSES: + Code 202 +Transaction Request without callbackUrl + { + "transactionResultId": "0821032398-1628774190395", + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + +Transaction Request with callbackUrl and token + { + "statusMessage": "Operation Accepted", + "transactionReference":"00000000-0000-0000-0000-000000000000" + } + + Code 400 Ex:DeviceIsBusy + { + "error": { + "statusCode": 400, + "name":"BadRequestError", + "message": { + "error": 1001, + "message":"The device is busy" + } + } + } +``` + + +## /transaction-result/{transactionResultId} + + +`TransactionResultRetrieval` + +GET endpoint used to retrieve transaction results from the payment terminal. In case you do not provide a callbackURL and token in the transaction request, the terminal will post the transaction result to an Handpoint internal API which can be queried in order for your software to fetch the transaction result. If you are running a server to receive results and pass a callback URL and token as part of the transaction request you do not need to query this endpoint. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionResultId` Required
*String* | The transactionResultId is a unique transaction id delivered immediately as a response to your transaction request. It can be used to query for a transaction result. | + + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **No Content** | Response code 204. The transactionResultId was found in the database but there is no transaction result associated yet. This status will be retrieved while the transaction is ongoing and the transaction result has not been delivered yet. | +| **OK** | Response code 200 + Transaction Result. The transactionResultId was found in the database and the associated Transaction Result object is delivered. | +| **Not Found** | Response code 404. The transactionResultId was not found in the database. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://cloud.handpoint.com/transaction-result/0821032398-1628774190395" (production) + "https://cloud.handpoint.io/transaction-result/0821032398-1628774190395" (development) + +RESPONSE: +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "cardholder name" +} +``` + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +## /transactions/{guid}/tip-adjustment + + +`TipAdjustment` + +POST endpoint used to execute a tip adjustment operation. + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Note: If two tip adjustments are sent for the same original transaction, only the second one will be taken into account. Each new tip adjustment will override the previous one. A tip adjustment will be rejected if the original transaction has already been batched out by the acquirer. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: guid` Required
*String* | The guid of the transaction to be adjusted. | +| `Request Body: Tip Adjustment` Required
[TipAdjustment](restobjects.md#tip-adjustment) | Object containing the amount and currency of the tip adjustment. | + +**Returns** + + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code 200. | +| **BadRequest** | Response code 400. | + + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl --location --request POST 'https://cloud.handpoint.com/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (production)\ + curl --location --request POST 'https://cloud.handpoint.io/transactions/ff6da784-8b57-11ed-9891-ebe2a88ff071/tip-adjustment' (development)\ + --header 'ApiKeyCloud: MeRcHaNt-ApI-KeY' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "amount": 5.25 + }' + +RESPONSE code 200: +{ + "statusMessage": "tip adjusted" +} + +Error example response (using invalid guid): +{ + "error": { + "statusCode": 400, + "name": "BadRequestError", + "message": "Invalid guid [fake-guid]" + } +} +``` + +## Transaction Result Recovery + + +`TransactionResultRecovery` + + The terminal has a transaction recovery loop to automatically send back the pending TransactionResult to the callback URL in case it becomes unreachable (network issue or server down). + + For the first 100 seconds after a transaction is completed, a background thread will attempt to deliver the result every 5 seconds. If the server is still unreachable after the first 100 seconds, the retry loop turns into an exponential increment to the power of 2 (8s-16s-32s etc…). + The recovery loop is reinitialized every time the Handpoint application is restarted or the startRecovery method is triggered. The Transaction Result received through the transaction recovery loop will have the **recoveredTransaction** field set to **true**. + + All 2XXs http response codes from the callbackUrl are valid to notify the payment terminal of a successful delivery of the result. + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [Transaction Result](restobjects.md#transaction-result-object) | The [Transaction Result](restobjects.md#transaction-result-object) is delivered to the callback URL from the [Transaction Request](restobjects.md#transaction-request-object). | + + + +## /transactions/{transactionReference}/status + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + + +The `https://transactions.handpoint.com/transactions/{transactionReference}/status` endpoint is a RESTful API endpoint designed to retrieve the status of the first transaction associated with a given `transactionReference`. This endpoint returns the status of the initial transaction linked to the reference, reflecting the current state of that transaction.The `transactionReference` is a unique value that you need to generate and pass in the original [ transaction request](restobjects.md#transactionRequest). + +The main transaction result [*FinancialStatus*](restobjects.md#financialStatus) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + +![getTrxStatusEndpoint](/img/getTransactionStatusEndpoint.drawio.png) + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path parameter: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It can then be used to query the transaction status endpoint. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **OK** | Response code **200** + [Transaction Result](restobjects.md#transaction-result-object).

There are two possible outcomes:
- The `transactionReference` was found in the database and the associated [Transaction Result](restobjects.md#transaction-result-object) object is delivered. By checking the [financial status](restobjects.md#financialStatus) field you will be able to know the status of the transaction at the time of the query.
- The `transactionReference` was not found in the Handpoint gateway. The [financial status](restobjects.md#financialStatus) received in this case will be `UNDEFINED` (NOT FOUND)| +| **Unauthorized** | Response code **401**. The client request has not been completed because it lacks valid authentication credentials for the requested resource. Please check your API Key is correct for this `transactionReference`. | +| **Forbidden** | Response code **403**. Authentication was unsuccessful. Please check your API Key is valid. | + +**Code Example** + +```shell +Operation executed using CLI tool CURL: +REQUEST: + curl -X GET \\ + -H"ApiKeyCLoud: MeRcHaNt-ApIkEy" \\ + "https://transactions.handpoint.com/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (production) + "https://transactions.handpoint.io/transactions/3e665342-a95b-49c1-b6fe-b3f102305a76/status" (development) + +RESPONSE: +{ + "aid": "A0000000031010", + "arc": "00", + "iad": "06011103A00000", + "tsi": "0000", + "tvr": "0000000000", + "cardEntryType": "ICC", + "cardLanguagePreference": "", + "currency": "USD", + "type": "SALE", + "tipAmount": 0, + "totalAmount": 100, + "requestedAmount": 100, + "dueAmount": 0, + "tipPercentage": 0, + "efttimestamp": "20230511110113006", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "verificationMethod": "UNDEFINED", + "authorisationCode": "123456", + "cardSchemeName": "Visa", + "cardToken": "", + "maskedCardNumber": "************5733", + "cardTypeId": "", + "customerReference": "", + "efttransactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "transactionID": "66d94f20-efda-11ed-929c-47fffda5f9b5", + "errorMessage": "", + "expiryDateMMYY": "0924", + "issuerResponseCode": "00", + "rrn": "0000511573740", + "tenderType": "CREDIT", + "unMaskedPan": "", + "merchantAddress": "Navalaosa 48770 Madrid", + "merchantName": "Hago la cama 2", + "mid": "", + "cardHolderName": "", + "chipTransactionReport": "", + "customerReceipt": "", + "merchantReceipt": "", + "signatureUrl": "", + "statusMessage": "", + "tid": "", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76", + "transactionOrigin": "", + "finStatus": "AUTHORISED" +} +``` + +## /transactions/{transactionReference}/status/{selector} + +:::warning +This endpoint does **not** use **https://cloud.handpoint.(io/com)/** as a base URL, it uses **https://transactions.handpoint.(io/com)/** +::: + +The `https://transactions.handpoint.io/transactions/{transactionReference}/status/{selector}` endpoint is a RESTful API that retrieves the status of transactions associated with a given `transactionReference`. The `{selector}` path parameter allows you to specify whether you want to retrieve the status of a specific transaction by its index or retrieve all transactions associated with the `transactionReference`. + +**Selector Values** + +| Selector | Description | +| ------------- | ----------- | +| all | Returns the status of all transactions associated with the given `transactionReference`. | +| first | Returns the status of the first transaction associated with the `transactionReference`. | +| last | Returns the status of the last transaction associated with the `transactionReference`. | +| {index} | Returns the status of a specific transaction identified by its 1-based index in the sequence of transactions associated with the `transactionReference`. For example, `1` for the first transaction, `2` for the second, and so on. | + + +:::caution +**Important Note:** The `finStatus` field for the first transaction reflects its current status. In contrast, for subsequent transactions, the finStatus reflects the original status at the time of processing. For example, if a refund is later reversed, the refund transaction will still show as AUTHORISED. +::: + + +**Parameters** + +| Parameter | Description | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required *String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Path: transactionReference` Required
*String* | The `transactionReference` is a **UNIQUE** [UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)) generated by you and added as a parameter to the initial financial request. It is used to query the transaction status.| +| `Path: selector` Required *String* | Specifies whether to return all transactions or a specific transaction by index. | + +:::caution +Handpoint does not verify that the `transactionReference` values sent on every request are **UNIQUE**. +It's our recommendation that a new value is created and sent for every request attempt. +::: + +**Responses** + +| Response | Response Code | +| ----------- | ----------- | +| **200 OK** | The request was successful, and the transaction status(es) are returned in the response.| +| **404 Not Found** |The specified `transactionReference` or `selector` does not exist.| +| **403 Forbidden** | Authentication failed. Please check that your API Key is valid.| + + +**Example Request** + + - Retrieve All Transactions: + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/all" + ``` + + + - Retrieve third transaction + + ```shell + curl -X GET \ + -H "ApiKeyCloud: your-api-key" \ + "https://transactions.handpoint.io/transactions/123e4567-e89b-12d3-a456-426614174000/status/3" + ``` + +## Device Control Commands + +> **Note:** +> The following commands are available for all devices running Android SDK version 7.1006.0 or later. + +Command Endpoint Format + +All device control commands follow this endpoint structure: +```https://cloud.handpoint.io/devices/{deviceType}/{serialNumber}/{command}``` + +Where: +- `{deviceType}` is the type of the device (e.g., PAXIM30) +- `{serialNumber}` is the serial number of the device (e.g., 1640013848) +- `{command}` is the specific command to execute + +Common Parameters + +All commands share these common parameters: + +| Parameter | Notes | +| ----------- | ----------- | +| `Header: ApiKeyCloud` Required
*String* | Api key used to authenticate the merchant. (UNIQUE per Merchant) | +| `Header: Content-Type` Required
*String* | Must be set to `application/json` | + +Common Response Codes + +| Response Code | Description | +|--------------|-------------| +| 202 | Request accepted, command will be executed | +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Invalid parameter value (when applicable) | + +--- + +:::caution +For the Commands to work properly, the Handpoint Payments App **MUST** be in **Integrated Mode** (enabled via **Handpoint TMS** and controlled by the merchant in the **Handpoint Payments App** Settings). Use the [`pingDevice` operation](restobjects#operation-types-description) to confirm the device is in Integrated Mode before you send these commands.
+If you attempt to send one of these commands and the device is not yet in Integrated Mode, you may receive a **202 Accepted** response but the command will not have been executed by the terminal. +::: + +### Set Unattended Mode + +`POST /devices/{deviceType}/{serialNumber}/set-unattended-mode` + +Enables or disables unattended mode on the device. +Unattended mode will disable the Bottom navigation bar containing the Home, back, recent buttons. +The Payment screen will be the only visible screen in the Handpoint Payments App. (Settings, Hisotry and Analytic tabs will not be accessible) + + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `status` | boolean | `true` to enable unattended mode, `false` to disable | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-unattended-mode" +``` + +### Set Locale + +`POST /devices/{deviceType}/{serialNumber}/set-locale` + +Sets the locale of the target device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|--------|-----------------------------------------------------------------------------| +| `locale` | string | IETF BCP 47 language tag (e.g., `en_US`). Two-letter language and country code.| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "locale": "en_CA" + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-locale" +``` + +--- + +### Set Password Protection + +`POST /devices/{deviceType}/{serialNumber}/set-password-protected` + +Enables or disables password protection on the device. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `status` | boolean | `true` to enable password protection, `false` to disable | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "status": true + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-password-protected" +``` + +--- + +### Reboot Device + +`POST /devices/{deviceType}/{serialNumber}/reboot` + +Reboots the device with an optional force parameter. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------------------------------| +| `force` | boolean | `true` to force reboot even during transaction, `false` to check status first| + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "force": false + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/reboot" +``` + +--- + +### Set Screen Brightness + +`POST /devices/{deviceType}/{serialNumber}/set-screen-brightness` + +Sets the screen brightness levels. + +**Request Body Parameters** + +| Parameter | Type | Description | +|--------------------------|---------|------------------------------------| +| `minimumBrightnessLevel` | integer | Value between 0 and 100 | +| `maximumBrightnessLevel` | integer | Value between 0 and 100 | + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "minimumBrightnessLevel": 20, + "maximumBrightnessLevel": 100 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-screen-brightness" +``` + +--- + +### Set Reboot Time + +:::note +This feature is only enabled for production devices. +::: + +`POST /devices/{deviceType}/{serialNumber}/set-reboot-time` + +Sets the daily reboot time for the device. The actual reboot will occur at a random minute within the specified hour. + +**Request Body Parameters** + +| Parameter | Type | Description | +|-----------|---------|-----------------------------------------------------| +| `hour` | integer | Hour of the day (0-23) when device should reboot | + +:::tip +If hour is set to 22, the device will reboot at a random time between 22:01 and 22:59. +::: + +**Response Codes** + +| Code | Description | +|------|---------------------------------------------| +| 202 | The request is accepted and will be executed| +| 403 | Authentication failed | +| 422 | Invalid request | +| 400 | Value is outside the valid range | + +**Example Request** + +```shell +curl -X POST \ + -H "ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" \ + -H "Content-Type: application/json" \ + -d '{ + "hour": 22 + }' \ + "https://cloud.handpoint.io/devices/PAXIM30/0000000000/set-reboot-time" +``` \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restintroduction.md b/restapi_versioned_docs/version-REST API 2.23.1/restintroduction.md new file mode 100644 index 0000000..5252785 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restintroduction.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +id: restintroduction +--- + +# Introduction +Use the Handpoint REST API to integrate leading smartpos terminals with your software. The Handpoint REST API is a simple REST interface that acts as a bridge between **your software and the payment terminal** , while shielding your software from unmasked card data. It is seamless to integrate, keeps you out of PCI scope, works with every platform, and lets you use the best Android terminals on the market. + +Complete your integration in just three steps: Initiate the interface, choose the terminal, and start the sale. It is as simple as it sounds. The only thing you need is a valid API key to authenticate against the API. Simply execute the financial operation, and within seconds you’ll get back the transaction result and receipts in your software. The Handpoint REST API seamlessly starts and manages the entire point to point encrypted transaction with the payment terminal, minimizing hassle for you and maximizing reliability, security, and control. + +## API Overview + +When integrating with the Handpoint REST API, there are 2 possible transaction flows in order to get back the transaction result from the payment terminal to your application: + +1. **Run a server to receive the transaction result**. In this scenario you will need to specify a callback URL in the transaction request. At the end of the transaction, the payment terminal will send back the transaction result to the specified callback URL. + +2. **Query an endpoint provided by Handpoint**. In this scenario a transaction result id is delivered immediately to your application as a response to the transaction request. In order to retrieve the transaction result, a specific API endpoint needs to be queried with the transaction id once the financial operation is completed on the payment terminal. + +## Transaction flow + +:::tip + +1. Pre-requisite: request your test credentials (API key) and a payment terminal from Handpoint. + +2. ensure you are targeting the correct environment. If your payment terminal is a **debug** terminal then the development environment (.io) needs to be targeted. If your payment terminal is a **demo** terminal or a **production** terminal then the production environment (.com) needs to be targeted. Demo terminals are production terminals linked to a mock acquirer so **funds are not moved**. To check if you should be using the production or the development environment you can refer to this guide: ["How do I know what type of card reader I have?"](https://hndpt.co/39utmzi) + +  **For production terminals the endpoint to target is:** https://cloud.handpoint.com/ + +  **For debug terminals the endpoint to target is:** https://cloud.handpoint.io/ + +::: + +The following flow shows the interactions between your application and the Handpoint REST API: + +**1)** Initialize your interface with the API key and receive the list of payment terminals available to perform a financial operation. Each API key is unique per merchant and needs to be configurable in your backend. Select a payment terminal and send a POST [transaction request](restobjects.md#transaction-request-object) to the REST API. + +**2)** The API will validate the request body and will immediately respond back to your software with the response code 202 ("Accepted”) to confirm that the data has been correctly forwarded to the payment terminal. Depending on your request body, a transactionResultId might be returned by the Handpoint API at this step (see 4.2 below). + +**3)** The validated transaction request object is forwarded to the payment terminal and the transaction starts. + +**4.1) If the original transaction request contains a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) will be sent back from the payment terminal to your software by using the callbackUrl. The token is a unique value generated by your software, it will be echoed in the custom HTTP header called AUTH-TOKEN of the transaction result sent by the terminal to your server. We recommend to use the token in order to authenticate the messages hitting your endpoint. The terminal expects a response back from your server when you receive the transaction result, 2XXs http response codes from the callbackUrl are considered as valid by the payment terminal to acknowledge a successful delivery of the transaction result. **See figure 4.1 below**. + +:::warning + +If you're going to use **4.1**, make sure to use an ssl certificate whose certification authority is supported by the versions of Android running on the payment terminals (Android versions vary between Android 5 and Android 10 depending on the terminal model) +::: + + **4.2) If the original transaction request does not contain a callbackUrl and token** , the [transaction result](restobjects.md#transaction-result-object) is sent back from the terminal to Handpoint's REST-API. The transaction result can then be retrieved from the endpoint GET [transaction-result/{transactionResultId}](restendpoints#transaction-resulttransactionresultid) where the transactionResultId (also called cloud transaction identifier) is found in the immediate answer from the initial transaction request POST to the REST-API (see step 2). **See figure 4.2 below**. + + + + +![Sandbox logo](/img/RestApiDiagram) + + diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restobjects.md b/restapi_versioned_docs/version-REST API 2.23.1/restobjects.md new file mode 100644 index 0000000..c6942dd --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restobjects.md @@ -0,0 +1,826 @@ +--- +sidebar_position: 7 +id: restobjects +--- + +# Objects + + +## Acquirer + +`Acquirer` Enum + + +An enum representing the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `OMNIPAY` `POSTBRIDGE` `TSYS` `VANTIV` `SANDBOX` + + +## Balance + +`Balance` Object + + +Balance available on the card. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The balance| +| `currency`
*Currency* | The balance currency| +| `positive`
*Boolean* | Defines if the balance is positive| +| `negative`
*Boolean* | Defines if the balance is negative| + +**Code example** + +````json +"balance": { + "amount": 1000, + "currency": "EUR", + "negative": false, + "positive": true + } +```` + +## Bypass Options + + +`BypassOptions` Object + + +Configuration to enable/disable signature or pin bypass. + +| Property | Description | +| ----------- | ----------- | +| `pinBypass`
*Boolean* | Enables/disables pin bypass. Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. | +| `signatureBypass`
*Boolean* | Enables/disables signature bypass. Whether the terminal prompts for a signature, depends on how you configure this parameter. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. | + +**Code example** + +````json +{ + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + } +} +```` + +## Card Entry Type{#cardEntryType} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + + +## Card Scheme Name {#cardSchemeName} + +`CardSchemeName` Enum + +An enum representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Currency + +`Currency` Enum + +An enum of currencies. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` `USD` `UZS` `VEF` + + +## Device {#deviceObject} + +`Device` Object + + +An object to store information about the payment terminal in use. ALL values are **REQUIRED**. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `merchant_id_alpha` Required
*String* | Merchant unique identifier associated with the payment terminal.| +| `serial_number` Required
*String* | Payment terminal serial number.| +| `ssk` Required
*String* | Payment terminal shared secret key to authenticate financial operations.| +| `terminal_type` Required
*String* | Payment terminal name composed of two parts "serial_number - terminal_type".| + +**Code example** + +````json +{ + "merchant_id_alpha": "Test_Merchant", + "serial_number": "614004878", + "ssk": "74817EA5C63437ADE7AA3A5401", + "terminal_type": "PAXA920" +} +```` + +## Device Status{#deviceStatus} + +`DeviceStatus` Object + + +A class which holds the payment terminal status. + + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | The serial number of the payment terminal.| +| `BatteryStatus`
*String* | The battery status in percentages of the payment terminal.| +| `BatterymV`
*String* | The battery milli volts of the payment terminal.| +| `BatteryCharging`
*String* | The battery charging status of the payment terminal.| +| `ExternalPower`
*String* | The status of the external power of the payment terminal.| +| `ApplicationName`
*String* | The application name used on the payment terminal.| +| `ApplicationVersion`
*String* | The application version number used on the payment terminal.| +| `bluetoothName`
*String* | The bluetooth interface name used on the payment terminal.| +| `statusMessage`
*String* | Device human readable status message.| + + +**Code example** + +````json +{ + "applicationName": "TestApp", + "applicationVersion": "20.1.0.1", + "batteryCharging": "Charging", + "batteryStatus": "100", + "batterymV": "4134", + "bluetoothName": "A920", + "externalPower": "USB", + "serialNumber": "0821032397", + "statusMessage": "Card reader time out" +} +```` + +## Financial Status{#financialStatus} + +`Financial Status` Enum + +An enum representing different statuses of a completed transaction. + +`UNDEFINED` `AUTHORISED` `DECLINED` `REFUNDED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND) *
|The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged..| +| `AUTHORISED`
| The transaction (Sale, Refund etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) request. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a `preAuthorizationCapture` message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status | + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) method. + + +## Merchant Auth + +`MerchantAuth` Object + +An object used to store merchant authentication parameters. This object is optional, it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. + + + +| Property | Description | +| ----------- | ----------- | +| `Credential`
[*Credential[]*](#merchant-auth-credential) | Array of credentials| + +**Code example** + +````json +{ + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }] +} +```` + +## Merchant Auth Credential + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer*](#acquirer) | If present, it links this credential to the specified acquirer. Only required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +````json +{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333" +} + +{ + "externalId": "4444" +} +```` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```json +{ + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + } +} +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | First and last name of the money transfer recipient. (**a-Z, A-Z** only)| +| `countryCode` Required
*CountryCode* | Country code of the recipient ([ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))| + +**Code example** + +```json +{ + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +``` + +## Operation Type + +`OperationType` Enum + + +An enum representing different types of operations. + + +Possible Values: + +`sale` `refund` `refundReversal` `saleReversal` `saleAndTokenizeCard` `tokenizeCard` `printReceipt` `cardPan` `pingDevice` `stopCurrentTransaction` `moToSale` `moToRefund` `moToReversal` `moToPreAuthorization` `preAuthorization` `preAuthorizationIncrease` `preAuthorizationCapture` `preAuthorizationReversal` + + + +## Operation Types Description + +`OperationTypesDescription` + + +| Parameter | Notes | +| ----------- | ----------- | +| `sale`
*String* | Sends a sale transaction to the payment terminal. This is the most basic operation used to withdraw funds from the cardholder's bank account. | +| `refund`
*String* | Sends a refund transaction to the payment terminal. This operation moves funds from the merchant account to the cardholder´s credit card. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. | +| `refundReversal`
*String* | A refund reversal, also called refund VOID, allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. | +| `saleReversal`
*String* | A sale reversal, also called sale VOID allows the merchant to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. | +| `saleAndTokenizeCard`
*String* | A sale operation which also returns a card token. This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `tokenizeCard`
*String* | Returns a card token (representing the card number). This functionality is not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice. | +| `printReceipt`
*String* | Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. **The format of the HTML data, stored in the URL or passed in the value of the `receipt` key, must follow this format: [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format)** | +| `cardPan`
*String* | A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. | +| `pingDevice`
*String* | This operation will ping the terminal to confirm if it is ready to process transactions. `returnDeviceInfo` can be se to `true` in the body parameters to return device information like App Version, Sdk Version, Firmware Version and Battery information | +| `stopCurrentTransaction`
*String* | Operation used to stop the current transaction. The transaction can only be stopped at specific stages of payment processing, for example a transaction can not be stopped when the card is being read but can be stopped when waiting for the cardholder to initially insert a card. | +| `moToSale`
*String* | Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. | +| `moToRefund`
*String* | A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. Triggering this function will prompt a card input form on the terminal for the merchant to enter the card number, expiry date and CVV of the card to be charged. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. | +| `moToReversal`
*String* | A MOTO reversal, also called VOID allows the user to reverse a previous MOTO sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. | +| `moToPreAuthorization`
*String* | A MOTO pre-authorization, sends a pre-authorization transaction to the payment terminal. A pre-authorization charge is a temporary hold placed on a customer’s payment card. It’s used to verify that the account is valid and has sufficient funds to cover a pending transaction. | +| `preAuthorization`
*String* | A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. | +| `preAuthorizationIncrease`
*String* | This operation allows the merchant to **increase/decrease** the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function.| +| `preAuthorizationCapture`
*String* | A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank.
**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued.
Check out the [card brand rules](restobjects.md#pre-auth-capture-card-brand-rules). | +| `preAuthorizationReversal`
*String* | A **Pre-Auth/Capture Reversal** allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the Pre-Auth Increase/Decrease operation.

A Pre-Auth/Capture reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](restobjects.md#financialStatus) -> [AUTHORISED](restobjects.md#financialStatus)). | + + +### Pre-Auth Capture Card Brand Rules + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + +## Payment Scenario{#paymentScenario} + + +`PaymentScenario` Enum + + +An enum representing different types of payment scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + + +## Status + +`status` Enum + + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + + +## Status Info + +`StatusInfo` Object + + +A class containing information about the status of the transaction. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `cancelAllowed`
*boolean* | A `boolean` Letting the integrator know if the terminal will accept a stop transaction request.) | +| `status`
[*Status*](#status) | A `Status` enum representing the status of the transaction. | +| `message`
*String* | A `String` containing the status message of the transaction. | +| `deviceStatus`
[*DeviceStatus*](#device-status) | A `DeviceStatus` object containing information about the payment terminal. | + + +## Tender Type{#tenderType} + +`TenderType` Enum + + +An enum representing different tender types. + +Possible values + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Adjustment + +`TipAdjustment` Object + + +| Property | Description | +| ----------- | ----------- | +| `amount`
*Biginteger* | Exact amount of the tip, including decimal digits. Currency will be extracted from the original transaction. | + +**Code example** + +````json +{ + "amount": 10.25 +} + +{ + "amount": 20 +} +```` + +## Tip Configuration + +`TipConfiguration` Object + + +| Property | Description | +| ----------- | ----------- | +| `baseAmount`
*String* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount. | +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip | +| `tipPercentages` Required
*List* | List of percentages used to calculate the tip amount. | +| `enterAmountEnabled`
*boolean* |Flag used to enable the cardholder to manually enter the tip amount. Default: true | +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true | +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string | + +**Code example** + +````json +{ + "tipConfiguration":{ + "baseAmount":"2000", + "headerName":"", + "tipPercentages":[ + 5, + 10, + 15, + 20, + 25 + ], + "enterAmountEnabled":true, + "skipEnabled":false, + "footer":"Thank you!!! ;)" + } + } +```` + +## Transaction Request Object {#transactionRequest} + +`TransactionRequest` Object + + +An object to store information about the request sent to the payment terminal. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `operation` Required
[*OperationTypesDescription*](#operation-types-description) | The type of operation to be performed. | +| `serial_number` Required
*String* | Payment terminal serial number. | +| `terminal_type` Required
*String* | Type of terminal. | +| `callbackUrl`
*String* | If used,this is the url the payment terminal will use to send the Transaction Result once the operation is complete. All 2XXs http response codes from the callbackUrl (your server) are valid to notify the terminal of a successful delivery of the result. If the callbackUrl is not present, the device will send back the transaction result to Handpoint's REST-API and results can be retrieved using the Transaction Result Retrieval endpoint. | +| `token`
*String* | If used, the token is a unique value per operation generated by your software and used to authenticate the transaction result sent through the callbackUrl against your server. The token will be injected in the request header with key value 'AUTH-TOKEN'. **REQUIRED** when the callbackUrl is present. | +| `customerReference`
*String* | Transaction identifier provided by your software. The customerReference sent in the TransactionRequest object is echoed in the TransactionResult. In case the transaction outcome is unknown (network issue or other) and for some unknown reason your software did not receive any result. The customerReference can be used to query the Handpoint Transaction API and check if a specific transaction was approved or not: https://txnfeedapi.handpoint.com/#api-Transactions-getTxnByCustomerReference. | +| `amount`
*String* | Amount of the transaction - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `currency`
[*Currency*](#currency) | The currency of the transaction. **REQUIRED** for operations: sale, refund, refundReversal, saleReversal and saleAndTokenizeCard. | +| `originalTransactionId`
*String* | The transaction id of the original operation to be reversed. Only required to reverse or refund a transaction and for operations linked to a pre-authorisation. **REQUIRED** for operations: refundReversal, saleReversal, LINKED refunds, preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal. | +| `receipt`
*String* | HTML receipt, following the format defined in Html Print Format, or url to locate the receipt, it can be found in the response of a Transaction Request, in the fields merchantReceipt or customerReceipt. **REQUIRED** for operations: printReceipt. The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `tipConfiguration`
[*TipConfiguration*](#tip-configuration) | Configuration to enable tipping. At the time of sale, a tip menu will be shown to the cardholder with the predefined configuration. The tip configuration is optional and can only be used with the sale and saleAndTokenize operations. | +| `bypassOptions`
[*ByPassOptions*](#bypass-options) | Configuration to enable the possibility of bypassing signature or pin. The bypass configuration is optional and can only be used with the sale, saleAndTokenize and refund operations. | +| `merchantAuth`
[*MerchantAuth*](#merchant-auth) |Object used to store merchant authentication. it allows a transaction to be funded to a specific merchant account other than the default one. It is useful if a terminal is shared between multiple merchants, for example at an Hair Salon or a Doctor's office. The merchantAuth is optional and can only be used with the sale, saleAndTokenize and refund operations. For reversals, the credentials passed for the original sale will be automatically looked up by Handpoint and used to process the reversal. | +| `duplicate_check`
*Boolean* |Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe.



** The duplicate_check functionality is available for the following transaction types:** Sale, Sale and Tokenize, Sale Reversal, Refund, Refund Reversal, MoTo Sale, MoTo Refund and MoTo Reversal.


The `duplicate_check` service is **enabled to "true" by default**, if you want to disable it, you must explicitly pass the `duplicate_check` flag as part of the transaction request with the value "false".| +| `metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `transactionReference`
*String* | The `transactionReference` is a unique ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) that you need to generate and add to every transaction request. In case something goes wrong and you do not receive a transaction result from the terminal, you will be able to query the Handpoint gateway directly with this id by using the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](restobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions. The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund | +| `tokenize`
*Boolean* | Used to enable the tokenization flow in Tokenized Payments Operationss. See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information.| +| `cardPresent`
*Boolean* | Optional parameter to indicate that a reversal operation will imply an actual present card, and this will be taken into account in the payments flow. See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on how to use this feature.| + +**Code example** + +````json +// Result will be served to result.com +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "callbackUrl": "https://result.com", + "token": "123456789", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} + +// Result will be served back to Handpoint's REST-API +{ + "operation": "sale", + "amount": "10000", + "currency": "EUR", + "terminal_type": "PAXA920", + "serial_number": "1547854757", + "customerReference": "storeSale12548", + "transactionReference": "2bfde1fc-23b1-4c67-93d9-1d4a557f4d4f", + "tipConfiguration": { + "baseAmount": "2000", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" + }, + "bypassOptions": { + "signatureBypass": true, + "pinBypass": true + }, + "merchantAuth": [{ + "acquirer": "ACQ_DUMMY", + "mid": "1111", + "tid": "2222", + "mcc": "3333", + "externalId": "4444" + }], + "duplicate_check": true, + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "moneyRemittanceOptions":{ + "fullName":"John Doe", + "countryCode":"USA" + } +} +```` + + +## Transaction Result Object {#transactionResult} + +`TransactionResult` Object + + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `aid`
*String * | EMV Application Identifier of the card (EMV tag 9F06)| +| `arc`
*String * | EMV Authorisation Response Code (EMV tag 8A)| +| `authorisationCode`
*String * | Acquirer response code| +| `balance`
[*Balance*](#balance) | Balance available on the card| +| `batchNumber`
*String * | If available from the acquirer, the batch number where this transaction has been included| +| `budgetNumber`
*String * | Used to split payments over a period of months| +| `cardEntryType`
[*CardEntryType*](#cardEntryType) | Method used by the terminal to read the card| +| `cardLanguagePreference`
*String * | Preferred language of the card (EMV tag 5F2D)| +| `cardSchemeName`
[*CardSchemeName*](#cardSchemeName) | The brand of the card| +| `cardToken`
*String * | Token representing the PAN of the card| +| `chipTransactionReport`
*String * | Full report of the card EMV parameters| +| `currency`
[*Currency*](#currency) | The currency used for the transaction| +| `customerReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `customerReference`
*String * | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `deviceStatus`
[*DeviceStatus*](#deviceStatus) | Status of the payment terminal| +| `dueAmount`
*BigInteger * | In case of a partial approval for the transaction, this field contains the amount which remains to be paid. Partial approval support is only required by the card brands in the United States| +| `efttimestamp`
*BigInteger * | Time of the transaction (based on the date and time of the payment terminal)| +| `efttransactionID`
*String * | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String * | Detailed reason for the transaction error| +| `expiryDateMMYY`
*String * | Expiry date of the card used for the operation| +| `finStatus`
[*FinancialStatus*](#financialStatus) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED"| +| `iad`
*String * |EMV Issuer Application Data (EMV tag 9F10)| +| `issuerResponseCode`
*String * | Response code from the card issuer| +| `maskedCardNumber`
*String * | Masked card number of the card used for the operation| +| `merchantAddress`
*String * | Merchant Address| +| `merchantName`
*String * | Merchant Name| +| `merchantReceipt`
*String * | The receipts are usually received as URLs in the transaction result from the terminal but note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats.| +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String * | Merchant Identifier| +| `originalEFTTransactionID`
*String * | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed| +| `paymentScenario`
[*PaymentScenario*](#paymentScenario) | Indicates the card entry mode| +| `recoveredTransaction`
*Boolean * | This flag is set to true if the transaction result is sent through the transaction recovery logic explained in the Recovey Section, false otherwise| +| `requestedAmount`
*BigInteger * | The requested amount is the transaction amount sent to the terminal| +| `rrn`
*String * | Retrieval Reference Number, unique number assigned by the acquirer| +| `signatureUrl`
*String * | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String * | The status of the transaction, for example "Waiting for pin"| +| `tenderType`
[*TenderType*](#tenderType) | Transaction tender type (credit / debit)| +| `tid`
*String * | Terminal Identifier| +| `tipAmount`
*BigInteger * | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `tipPercentage`
*Double * | If tipping is enabled, this field will return the tip percentage added on top of the base amount| +| `totalAmount`
*BigInteger * | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality| +| `transactionID`
*String * | The transaction id is a terminal internal counter incremented for each transaction| +| `tsi`
*String * | EMV Transaction Status Information (EMV tag 9B)| +| `tvr`
*String * | EMV Transaction Verification Results (EMV tag 95)| +| `type`
[*TransactionType*](#transactionType) | The type of transaction initiated, for example "SALE"| +| `unMaskedPan`
*String * | Unmasked PAN, only received if the card is a non-payment card (loyalty)| +| `verificationMethod`
[*VerificationMethod*](#verificationMethod) | cardholder verification method, for example "PIN"| +| `multiLanguageStatusMessages`
*Map * | `map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map * | `map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String * | Name of the cardholder| +| `transactionReference`
*String* | The unique UUID associated with the transaction, it can be used to query the [get transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint.| + +**Code example** + +````json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1": "data1", + "metadata2": "data2", + "metadata3": "data3", + "metadata4": "data4", + "metadata5": "data5" + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "cardHolderName": "Mr/Mrs card holder full name", + "transactionReference": "3e665342-a95b-49c1-b6fe-b3f102305a76" +} + +```` + + +## Transaction Type{#transactionType} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `CARD_PAN` `CANCEL_TRX` `MOTO_SALE` `MOTO_REFUND` `MOTO_REVERSAL` + + + +## Verification Method{#verificationMethod} + +`VerificationMethod` Enum + +An enum representing the possible verification methods used during the transaction. + +Possible values: + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restprocessingpayments.md b/restapi_versioned_docs/version-REST API 2.23.1/restprocessingpayments.md new file mode 100644 index 0000000..91e60f2 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restprocessingpayments.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 3 +id: restprocessingpayments +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restreleasenotes.md b/restapi_versioned_docs/version-REST API 2.23.1/restreleasenotes.md new file mode 100644 index 0000000..5b1b534 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restreleasenotes.md @@ -0,0 +1,127 @@ +--- +sidebar_position: 2 +id: restreleasenotes +--- + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 2.23.1 +**Features:** + +The batch number is returned in the Transaction Result object now as `batchNumber`, provided the acquirer returns it. Please see [Transaction Result Object](restobjects.md#transactionResult) + +## 2.23.0 +**Bug fixes:** + +Support for MOTO operations in the Get Transaction Status service has been added + +## 2.22.4 +**Bug fixes:** + +Internal performance issues have been solved. + +## 2.22.3 +**Bug fixes:** + +A external vulnerability has been addressed. + +## 2.22.2 +**Features:** + +A new `cardPresent` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1010.5](/android/androidreleasenotes#710105) and [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for detailed information on the purpose of this feature. + +## 2.20.0 +**Features:** + +Added a selector to the [{transactionReference}/status](restendpoints.md#transactionstransactionreferencestatusselector) endpoint which improves greatly on reporting + +Added "commands" to allow greater device control options + +A new `tokenize` parameter is available under [Optional Transaction Parameters](restobjects.md#transactionRequest). See [Android SDK 7.1009.5](/android/androidreleasenotes#710095) and [Tokenized Payments Operations](/android/androidtransactions#cloudTokenizedPaymentsOperations) for detailed information on how to use this feature. + +## 2.17.0 +**Features:** + +We're excited to announce the latest update to our REST API, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](restobjects.md#money-remittance-options), which must be used in the operation. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + + +## 2.15.0 +**Features:** + +We are introducing a new transaction type called [Pre-Authorization](restobjects#operation-types-description). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased (Pre-Auth Increase), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured (Pre-Auth Capture) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released (Pre-Auth Reversal), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. + +In the [POSTMAN Collection](restapidownloads) section you will find sample code for each of these operations. + +## 2.14.0 +**Features:** + +We are introducing a new feature called [Get Transaction Status](restendpoints.md#transactionstransactionreferencestatus). This new [endpoint](restendpoints.md#transactionstransactionreferencestatus) allows you to query the Handpoint Gateway for the status of a transaction at any given time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +When a financial operation is started from the REST API, you need to provide a `transactionReference` in the body of the transaction [request](restobjects.md#transactionRequest). This `transactionReference` can then be used to query the status of a transaction (using the [transaction status](restendpoints.md#transactionstransactionreferencestatus) endpoint) if you are not receiving the result from the terminal in a timely fashion. The `transactionReference` must be a unique identifier ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))). + +Example request/response to the transaction status endpoint: + +![SaleWithGetTrxStatusExample](/img/RestAPIexample.png) + +## 2.13.0 + +**Features:** + +We are introducing a new feature called [**Transaction Metadata**](restobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Payments app **v4.1.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +**Fixes:** + +- Parsing errors from the gateway (Tip Adjustment). + +## 2.12.0 +**Features:** +- New endpoint [Tip-Adjustment](restendpoints.md#transactionsguidtip-adjustment). + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. + + +## 2.10.0 +**Features:** + +We are introducing a new feature called duplicate payment check. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge. This menu will automatically be prompted on the payment terminal if a suspicious charge is detected. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. + +The duplicate payment check feature will be **enabled by default** when the Handpoint Payments app **v4.0.0.** or higher is used. V2.10.0 of the REST API only allows you to disable the duplicate payment check feature if you wish to not support it. + +The new `duplicate_check` parameter is available under the [Transaction Request Object](restobjects.md#transactionRequest). + +## 2.7.1 +**Features:** +- New endpoint to create, get and delete API keys for Merchants + +## 2.7.0 +**Features:** + +- Mail/Telephone Order functionality +- Retry logic for transaction triggering + +## 2.6.0 +**Features:** +- Endpoints for virtual terminals + +## 2.4.0 +**Features:** + +- Transaction result retrieval through API endpoint GET .../transaction-result/{transactionResultId} diff --git a/restapi_versioned_docs/version-REST API 2.23.1/restsandbox.md b/restapi_versioned_docs/version-REST API 2.23.1/restsandbox.md new file mode 100644 index 0000000..0ec32b7 --- /dev/null +++ b/restapi_versioned_docs/version-REST API 2.23.1/restsandbox.md @@ -0,0 +1,44 @@ +--- +sidebar_position: 5 +id: restsandbox +--- + +# Handpoint Sandbox + +Get started today with the Handpoint sandbox and test payment transactions right in your browser. The sandbox is available here: http://www.handpoint.com/lab/cloudpos. **A payment terminal is required to start testing.** + + +This is the initial setup screen: + +![Sandbox logo](/img/cloudpos.png) + +To get started, select the target environment in which you are going to operate (Sandbox or Production). If you have any doubts selecting the correct environment, click on "*How do I know what type of card reader I have?*" and you will be redirected to an explanation page. + +![Sandbox logo](/img/cloudpos2.png) + +Next, enter your Handpoint API key in the box labeled "*INSERT API KEY*” and save. This action will automatically populate the “*SELECT A DEVICE*” drop down with the list of payment terminals assigned to your test account. If the API key is not valid, an error message will appear in the “RESPONSES” section of the sandbox. + +![Sandbox logo](/img/cloudpos3.png) + +In the “*SELECT A DEVICE*” list choose any of the payment terminals assigned to your account. You can refresh the “*SELECT A DEVICE*” list by clicking the refresh button on the right side of the “*SELECT A DEVICE*” box. If you are already connected to a device, you can disconnect from it using the “*Disconnect*” button or trigger a software and configuration update operation by using the "*Update*" button. + +![Sandbox logo](/img/cloudpos4.png) + +Once you have selected a device, the “SELECT A DEVICE” box will be disabled, and the rest of the sandbox will be enabled. With your selected device, you can simulate a number of operations, including: + +- Sale +- Sale and tokenize +- Refund +- Tokenize card +- Reverse sale transactions +- Reverse refund transactions + +In order to reverse a transaction, a transaction id is needed, this id is available in the transaction result data coming from a previous sale or refund operation. Each transaction result will appear in the RESPONSES panel, on the right side of the screen. + +With each transaction result you will be able to perform several operations: +- View and print the merchant receipt +- View and print the customer receipt +- Reverse the transaction +- Copy the transaction result data, it is the raw JSON transaction result, as received by the application from the payment terminal. + +![Sandbox logo](/img/cloudpos5.png) \ No newline at end of file diff --git a/restapi_versioned_sidebars/version-REST API 2.23.1-sidebars.json b/restapi_versioned_sidebars/version-REST API 2.23.1-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/restapi_versioned_sidebars/version-REST API 2.23.1-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/restapi_versions.json b/restapi_versions.json index 61c455f..cd00d71 100644 --- a/restapi_versions.json +++ b/restapi_versions.json @@ -1,4 +1,5 @@ [ + "REST API 2.23.1", "REST API 2.23.0", "REST API 2.22.4", "REST API 2.22.3", From 8462595fa167573bbd58fcb4f64c7d6f60c469a1 Mon Sep 17 00:00:00 2001 From: Imanol Rio Uriondo Date: Tue, 18 Nov 2025 12:54:26 +0100 Subject: [PATCH 115/115] DOCWEB-86 (#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mering dev to Main (#135) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Add: Estonian as locale * Add: Preauth for JavaScript SDK * Add: Pre-Auth release notes, Win and JS docs, Postman collection * Update androidreleasenotes.md * Update androidtransactions.md * Update androidtransactions.md * Update javascriptreleasenotes.md * Update androidreleasenotes.md * Update javascriptreleasenotes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowstransactions.md --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * chore: Increase timeout GHA (#81) chore: Increase Timeout GHA wf deploy * Feature tokenize and modify operation (#84) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md --------- Co-authored-by: Antoine * Fix: Tokenize and modify code sample (#85) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md * Fix: TokenizeAndModify code sample --------- Co-authored-by: Antoine * Add: MoTo PreAuth for Android, JS SDK and REST API (#86) * CICD-55 (#87) chore: use new txn feed doc address * DOCWEB-80 (#88) fix: remove tipAmount for preAuth operations * SDK-3434 (#89) * fix: remove tipAmount parameter from PreAuthorizationCapture * chore: remove typo * fix: include moToPreAuthorization in operation types (possible values) (#90) * REST-API doc fix (#91) chore: add preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal to the operations that require the originalTransactionId parameter * Fixes PreAuth WinSDK (#92) Add: FAILED to GTS finStatus for WinSDK - Add: FAILED to GTS finStatus for WinSDK - Fix: Connect method integration guide for WinSDK - Fix: TipConfiguration code example for REST API * Preauth Rest Api (#93) Add: Card brand tables for PreAuth Capture Add: Card brand tables for PreAuth Capture Add: CAPTURED FinStatus Del: tip amount for PreAuth Increase & Capture * Add: New terminals and features (#94) Add: New terminals and features Fix: PreAuth Capture tables and Reversals info. * Created new SDKs and REST API versions (#95) * Fix: Preauth for all SDKs and REST API * Update androidtransactions.md * Update androidtransactions.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restobjects.md * Update restobjects.md * Update windowstransactions.md * Update windowstransactions.md --------- Co-authored-by: Antoine * Add new terminals, T&M Release notes (#96) * Add: BP50+, more terminals and T&M release Notes * Fix * Update androidreleasenotes.md * Update androidreleasenotes.md * Update cpdocs.js --------- Co-authored-by: Antoine * Add: Money Remittance docs (Android, JS, Win and REST API) (#98) * Add: Money Remittance docs (Android, JS, Win and REST API) * Update androidobjects.md * Update androidreleasenotes.md * Update androidobjects.md * Update androidreleasenotes.md * Update: Android SDK version (7.1004.1) * Update: REST API Postman Collection uodate * Update androidobjects.md * Update javascriptobjects.md * Update javascriptreleasenotes.md * Update restintroduction.md * Update restobjects.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowsobjects.md --------- Co-authored-by: Antoine * Add: New versions (Money Remittance) (#99) * Add mremittance examples (#101) * Add: Money Remittance code examples * Upd: Postman Collection with MRemittance examples * Add automatic refunds (#104) * Added Automatic Refunds Add: Automatic Refunds Fix: Report Configuration * Update Automatic Partial Refund * Update androidtransactions.md --------- Co-authored-by: Antoine * Add release notes 7.1004.2 (#105) * Added Release Notes 7.1004.2 Android SDK * Added Fix Slovenian formatting currency * Add: New version 7.1004.2 Android SDK (#106) * TMS landing page 2024 (Including TMS API docs link) (#108) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Updated Docs Links (#109) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Update docusarus.config links * Changed device name from HiLite Plus to BluePad 50+ (#111) Changed name from HiLite Plus to BluePad 50+ * Add sdk 7.1005.0 (#113) * Add 7.1005.0 SDK * updated admonition * Created version Android SDK 7.1005.0 (#114) Created version 7.1005.0 * Added new code example for USB (#116) * New GTS endpoint added (#117) * Removing HiPro, adding IM25 (#118) * EFTCLIENT-5268 Add tokenization operations in the JS SDK (#119) Adding documentation for JavaScript SDK version 7.2.2 * SDK-3815 (#120) * Add tokenize option in Windows SDK docs TODO: link this to the general description of our tokenize feature when ready, which is under development * Adding description of tokenized payments operations as a feature * Adding Android SDK 7.1009.5 version * Adding tokenized payments operations (standalone) * Adding missing Android SDK versions and adding draft of Tokenized Payments Operations overview TODO: complete 7.1009.4 release notes * Adding tokenized payments operations TODO: review text and format * Fixing some formatting * Linking to detailed information on tokenize in JS and Win SDKs * Integrationg Tokenize and Modify in new Tokenized Payments Operations * Removing PLM info that should not be public * Masking info * REST API and SDK updates (#121) * REST API and SDK updates Updating RestAPI endpoints: Added commands, small fixes Updating SDK versions -> removed maven repository and indicate Nexus for both dev and prod SDK versions. Removed A8900 from release notes. converted mermaid to PNG diagrams due to docusaurus v2.1.0 limitations * corrected links for restobjects.md changed restobjects.md to restobjects, looks like the build test doesn't like it in github although it does run locally * corrected typo on link causing broken link * rolled back acquirer's ENUM (#122) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * removed HiPro reference from iOS SDK (#123) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * Add tokenize parameter (#125) * added tokenize parameter Added tokenize parameter to restAPI documentation in Objects and in release Notes corrected tokenize parameter type in windows SDK * add tokenize parameter REST API: added tokenize parameter to both transaction object and to release notes Windows SDK: corrected the tokenize parameter type from String to Boolean * SDK-3856 iOS SDK 4.0.2 (#129) * feat: included version 4.0.2 * chore: removed unused section * feat: included release notes section for SDK iOS * docs: SDK-3854_1 Update README (#128) * docs: SDK-3854_2 Add info about Docusaurus (#131) * SDK-3887 (#132) feat: Adding Android SDK 7.1010.1 version * SDK-3886 (#133) ➕ A8900 ➕ iOS 4.0.2 ➖ manual 'entry transaction' references under MoTo ➖ HiLite Logs gathering info (not available for Prod devices) * Add a8900 description (#134) Added communications row for A8900 --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Miguel Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Co-authored-by: Vicente Pavón <30615276+vicentepdj@users.noreply.github.com> Co-authored-by: Raul Carrasco * SDK-3901-1 (#139) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Add: Estonian as locale * Add: Preauth for JavaScript SDK * Add: Pre-Auth release notes, Win and JS docs, Postman collection * Update androidreleasenotes.md * Update androidtransactions.md * Update androidtransactions.md * Update javascriptreleasenotes.md * Update androidreleasenotes.md * Update javascriptreleasenotes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowstransactions.md --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * chore: Increase timeout GHA (#81) chore: Increase Timeout GHA wf deploy * Feature tokenize and modify operation (#84) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md --------- Co-authored-by: Antoine * Fix: Tokenize and modify code sample (#85) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md * Fix: TokenizeAndModify code sample --------- Co-authored-by: Antoine * Add: MoTo PreAuth for Android, JS SDK and REST API (#86) * CICD-55 (#87) chore: use new txn feed doc address * DOCWEB-80 (#88) fix: remove tipAmount for preAuth operations * SDK-3434 (#89) * fix: remove tipAmount parameter from PreAuthorizationCapture * chore: remove typo * fix: include moToPreAuthorization in operation types (possible values) (#90) * REST-API doc fix (#91) chore: add preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal to the operations that require the originalTransactionId parameter * Fixes PreAuth WinSDK (#92) Add: FAILED to GTS finStatus for WinSDK - Add: FAILED to GTS finStatus for WinSDK - Fix: Connect method integration guide for WinSDK - Fix: TipConfiguration code example for REST API * Preauth Rest Api (#93) Add: Card brand tables for PreAuth Capture Add: Card brand tables for PreAuth Capture Add: CAPTURED FinStatus Del: tip amount for PreAuth Increase & Capture * Add: New terminals and features (#94) Add: New terminals and features Fix: PreAuth Capture tables and Reversals info. * Created new SDKs and REST API versions (#95) * Fix: Preauth for all SDKs and REST API * Update androidtransactions.md * Update androidtransactions.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restobjects.md * Update restobjects.md * Update windowstransactions.md * Update windowstransactions.md --------- Co-authored-by: Antoine * Add new terminals, T&M Release notes (#96) * Add: BP50+, more terminals and T&M release Notes * Fix * Update androidreleasenotes.md * Update androidreleasenotes.md * Update cpdocs.js --------- Co-authored-by: Antoine * Add: Money Remittance docs (Android, JS, Win and REST API) (#98) * Add: Money Remittance docs (Android, JS, Win and REST API) * Update androidobjects.md * Update androidreleasenotes.md * Update androidobjects.md * Update androidreleasenotes.md * Update: Android SDK version (7.1004.1) * Update: REST API Postman Collection uodate * Update androidobjects.md * Update javascriptobjects.md * Update javascriptreleasenotes.md * Update restintroduction.md * Update restobjects.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowsobjects.md --------- Co-authored-by: Antoine * Add: New versions (Money Remittance) (#99) * Add mremittance examples (#101) * Add: Money Remittance code examples * Upd: Postman Collection with MRemittance examples * Add automatic refunds (#104) * Added Automatic Refunds Add: Automatic Refunds Fix: Report Configuration * Update Automatic Partial Refund * Update androidtransactions.md --------- Co-authored-by: Antoine * Add release notes 7.1004.2 (#105) * Added Release Notes 7.1004.2 Android SDK * Added Fix Slovenian formatting currency * Add: New version 7.1004.2 Android SDK (#106) * TMS landing page 2024 (Including TMS API docs link) (#108) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Updated Docs Links (#109) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Update docusarus.config links * Changed device name from HiLite Plus to BluePad 50+ (#111) Changed name from HiLite Plus to BluePad 50+ * Add sdk 7.1005.0 (#113) * Add 7.1005.0 SDK * updated admonition * Created version Android SDK 7.1005.0 (#114) Created version 7.1005.0 * Added new code example for USB (#116) * New GTS endpoint added (#117) * Removing HiPro, adding IM25 (#118) * EFTCLIENT-5268 Add tokenization operations in the JS SDK (#119) Adding documentation for JavaScript SDK version 7.2.2 * SDK-3815 (#120) * Add tokenize option in Windows SDK docs TODO: link this to the general description of our tokenize feature when ready, which is under development * Adding description of tokenized payments operations as a feature * Adding Android SDK 7.1009.5 version * Adding tokenized payments operations (standalone) * Adding missing Android SDK versions and adding draft of Tokenized Payments Operations overview TODO: complete 7.1009.4 release notes * Adding tokenized payments operations TODO: review text and format * Fixing some formatting * Linking to detailed information on tokenize in JS and Win SDKs * Integrationg Tokenize and Modify in new Tokenized Payments Operations * Removing PLM info that should not be public * Masking info * REST API and SDK updates (#121) * REST API and SDK updates Updating RestAPI endpoints: Added commands, small fixes Updating SDK versions -> removed maven repository and indicate Nexus for both dev and prod SDK versions. Removed A8900 from release notes. converted mermaid to PNG diagrams due to docusaurus v2.1.0 limitations * corrected links for restobjects.md changed restobjects.md to restobjects, looks like the build test doesn't like it in github although it does run locally * corrected typo on link causing broken link * rolled back acquirer's ENUM (#122) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * removed HiPro reference from iOS SDK (#123) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * Add tokenize parameter (#125) * added tokenize parameter Added tokenize parameter to restAPI documentation in Objects and in release Notes corrected tokenize parameter type in windows SDK * add tokenize parameter REST API: added tokenize parameter to both transaction object and to release notes Windows SDK: corrected the tokenize parameter type from String to Boolean * SDK-3856 iOS SDK 4.0.2 (#129) * feat: included version 4.0.2 * chore: removed unused section * feat: included release notes section for SDK iOS * docs: SDK-3854_1 Update README (#128) * docs: SDK-3854_2 Add info about Docusaurus (#131) * SDK-3887 (#132) feat: Adding Android SDK 7.1010.1 version * SDK-3886 (#133) ➕ A8900 ➕ iOS 4.0.2 ➖ manual 'entry transaction' references under MoTo ➖ HiLite Logs gathering info (not available for Prod devices) * Add a8900 description (#134) Added communications row for A8900 * SDK-3901 (#136) Adding Android SDK 7.1010.2 documentation * Resolving versions conflict (#138) mering dev to Main (#135) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now … * Dev to Main (#137) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock Co-authored-by: ecunado * fix: add static/CNAME file (#17) Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' Co-authored-by: ecunado * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh Co-authored-by: ecunado * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP Co-authored-by: ecunado * chore: testing staging deployment Co-authored-by: ecunado * chore: testing staging deployment WIP Co-authored-by: ecunado * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide Co-authored-by: Miguel Co-authored-by: ecunado * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow Co-authored-by: ecunado * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation Co-authored-by: carlos * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README Co-authored-by: carlos Co-authored-by: imanol * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md Co-authored-by: carlos Co-authored-by: imanol * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag Co-authored-by: carlos Co-authored-by: Ezequiel Cuñado * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md Co-authored-by: Antoine * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md Co-authored-by: Antoine * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- Co-authored-by: Antoine * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- Co-authored-by: Antoine * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- Co-authored-by: Miguel * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- Co-authored-by: Antoine * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- Co-authored-by: Antoine * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * Add: Estonian as locale * Add: Preauth for JavaScript SDK * Add: Pre-Auth release notes, Win and JS docs, Postman collection * Update androidreleasenotes.md * Update androidtransactions.md * Update androidtransactions.md * Update javascriptreleasenotes.md * Update androidreleasenotes.md * Update javascriptreleasenotes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowstransactions.md --------- Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Imanol Rio Uriondo Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> * chore: Increase timeout GHA (#81) chore: Increase Timeout GHA wf deploy * Feature tokenize and modify operation (#84) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md --------- Co-authored-by: Antoine * Fix: Tokenize and modify code sample (#85) * Add: Tokenize And Modify operation * Fix: Code sample comment * Update androidtransactions.md * Update androidobjects.md * Update androidobjects.md * Fix: TokenizeAndModify code sample --------- Co-authored-by: Antoine * Add: MoTo PreAuth for Android, JS SDK and REST API (#86) * CICD-55 (#87) chore: use new txn feed doc address * DOCWEB-80 (#88) fix: remove tipAmount for preAuth operations * SDK-3434 (#89) * fix: remove tipAmount parameter from PreAuthorizationCapture * chore: remove typo * fix: include moToPreAuthorization in operation types (possible values) (#90) * REST-API doc fix (#91) chore: add preAuthorizationIncrease, preAuthorizationCapture and preAuthorizationReversal to the operations that require the originalTransactionId parameter * Fixes PreAuth WinSDK (#92) Add: FAILED to GTS finStatus for WinSDK - Add: FAILED to GTS finStatus for WinSDK - Fix: Connect method integration guide for WinSDK - Fix: TipConfiguration code example for REST API * Preauth Rest Api (#93) Add: Card brand tables for PreAuth Capture Add: Card brand tables for PreAuth Capture Add: CAPTURED FinStatus Del: tip amount for PreAuth Increase & Capture * Add: New terminals and features (#94) Add: New terminals and features Fix: PreAuth Capture tables and Reversals info. * Created new SDKs and REST API versions (#95) * Fix: Preauth for all SDKs and REST API * Update androidtransactions.md * Update androidtransactions.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update androidtransactions.md * Update javascripttransactiontypes.md * Update javascripttransactiontypes.md * Update restobjects.md * Update restobjects.md * Update windowstransactions.md * Update windowstransactions.md --------- Co-authored-by: Antoine * Add new terminals, T&M Release notes (#96) * Add: BP50+, more terminals and T&M release Notes * Fix * Update androidreleasenotes.md * Update androidreleasenotes.md * Update cpdocs.js --------- Co-authored-by: Antoine * Add: Money Remittance docs (Android, JS, Win and REST API) (#98) * Add: Money Remittance docs (Android, JS, Win and REST API) * Update androidobjects.md * Update androidreleasenotes.md * Update androidobjects.md * Update androidreleasenotes.md * Update: Android SDK version (7.1004.1) * Update: REST API Postman Collection uodate * Update androidobjects.md * Update javascriptobjects.md * Update javascriptreleasenotes.md * Update restintroduction.md * Update restobjects.md * Update restreleasenotes.md * Update windowsreleasenotes.md * Update windowsobjects.md --------- Co-authored-by: Antoine * Add: New versions (Money Remittance) (#99) * Add mremittance examples (#101) * Add: Money Remittance code examples * Upd: Postman Collection with MRemittance examples * Add automatic refunds (#104) * Added Automatic Refunds Add: Automatic Refunds Fix: Report Configuration * Update Automatic Partial Refund * Update androidtransactions.md --------- Co-authored-by: Antoine * Add release notes 7.1004.2 (#105) * Added Release Notes 7.1004.2 Android SDK * Added Fix Slovenian formatting currency * Add: New version 7.1004.2 Android SDK (#106) * TMS landing page 2024 (Including TMS API docs link) (#108) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Updated Docs Links (#109) * Add: new card for TMS API (Landing page) * Upd: link to TMS API docs * Update docusarus.config links * Changed device name from HiLite Plus to BluePad 50+ (#111) Changed name from HiLite Plus to BluePad 50+ * Add sdk 7.1005.0 (#113) * Add 7.1005.0 SDK * updated admonition * Created version Android SDK 7.1005.0 (#114) Created version 7.1005.0 * Added new code example for USB (#116) * New GTS endpoint added (#117) * Removing HiPro, adding IM25 (#118) * EFTCLIENT-5268 Add tokenization operations in the JS SDK (#119) Adding documentation for JavaScript SDK version 7.2.2 * SDK-3815 (#120) * Add tokenize option in Windows SDK docs TODO: link this to the general description of our tokenize feature when ready, which is under development * Adding description of tokenized payments operations as a feature * Adding Android SDK 7.1009.5 version * Adding tokenized payments operations (standalone) * Adding missing Android SDK versions and adding draft of Tokenized Payments Operations overview TODO: complete 7.1009.4 release notes * Adding tokenized payments operations TODO: review text and format * Fixing some formatting * Linking to detailed information on tokenize in JS and Win SDKs * Integrationg Tokenize and Modify in new Tokenized Payments Operations * Removing PLM info that should not be public * Masking info * REST API and SDK updates (#121) * REST API and SDK updates Updating RestAPI endpoints: Added commands, small fixes Updating SDK versions -> removed maven repository and indicate Nexus for both dev and prod SDK versions. Removed A8900 from release notes. converted mermaid to PNG diagrams due to docusaurus v2.1.0 limitations * corrected links for restobjects.md changed restobjects.md to restobjects, looks like the build test doesn't like it in github although it does run locally * corrected typo on link causing broken link * rolled back acquirer's ENUM (#122) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * removed HiPro reference from iOS SDK (#123) * pingDevice wording, acquirer ENUM rollback minus EVO Improved pingDevice wording. rolledback change on acquirer ENUM removing 'EVO' * removed hipro from iOS SDK doc removed hiPro and lightning references found in docu * reviewed comments removed wrongly space and eg instead of f.ex which seems to come from Spanish * improved md syntax removed wrongly assigned spaces in ** and reviewed all instanced for corrections * more spaces added missing space * Add tokenize parameter (#125) * added tokenize parameter Added tokenize parameter to restAPI documentation in Objects and in release Notes corrected tokenize parameter type in windows SDK * add tokenize parameter REST API: added tokenize parameter to both transaction object and to release notes Windows SDK: corrected the tokenize parameter type from String to Boolean * SDK-3856 iOS SDK 4.0.2 (#129) * feat: included version 4.0.2 * chore: removed unused section * feat: included release notes section for SDK iOS * docs: SDK-3854_1 Update README (#128) * docs: SDK-3854_2 Add info about Docusaurus (#131) * SDK-3887 (#132) feat: Adding Android SDK 7.1010.1 version * SDK-3886 (#133) ➕ A8900 ➕ iOS 4.0.2 ➖ manual 'entry transaction' references under MoTo ➖ HiLite Logs gathering info (not available for Prod devices) * Add a8900 description (#134) Added communications row for A8900 * SDK-3901 (#136) Adding Android SDK 7.1010.2 documentation * Resolving versions conflict (#138) mering dev to Main (#135) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) * Add: Pax IM30 (#64) * Add get txn status (#66) * add: gettxnstatus_first_draft * add: Release Notes * Add: GetTxnStatus comments * add: diagrams, finStatus, Postman collection (#67) * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Pre-auth Android SDK code * Feature get txn status (#70) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Feature get txn status (#71) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * Fix texts and object types (getTxnStatus) (#68) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links --------- * update js/windows/android get txn status docs * rest api get txn status updates * Feature get txn status (#69) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates --------- * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature --------- * Add: Pre-auth operations type added to REST API * Feature get txn status (#73) * add: diagrams, finStatus, Postman collection * changed summary * Update javascriptreleasenotes.md * update REST API release notes * update android SDK get transaction status * update fin status description * Fix: Object type for fields - Fixed object types (dueAmount, efttimestamp)[WinSDK,JS SDK and REST API] - Fixed some links * update js/windows/android get txn status docs * rest api get txn status updates * Fix: Integration guides Android and Windows * Updated integration guides, postman collection - Updated integration guides (Android, JS, Windows) and Postman collection. - Deleted finStatus UNKNOWN (UNDEFINED will be used) -Added REFUNDED * Add: transactionStarted supporting transactionReference for Cloud * Fix: Transaction Started interface Android SDK * Add: Created new versions for GetTxnStatus feature * Fix: GetTxnStatus hostname, windowsSDK tip objects * Fix: RESTAPI hostname endpoint --------- * Added JS SDK link and languages (#74) Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Add links languages (#75) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Add links languages (#76) * Added JS SDK link and languages Added JS SDK link to 7.0.0 and de_DE & sl_SL languages to Android SDK * Fix: Integration Guides JS and Windows SDK * Fix: Comments Windows Integration Guide * Add MOTO to PaymentScenario (Android & Windows SDK) (#77) * Feature Preauth (Android, JS SDK, Win SDK and REST API) (#80) * Dev (#79) * Added Metada Feature with new SDKs versions (#63) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now an object (OperationStartResult) * fixed events error * little change * Added renamed event deviceCapabilities to mig. guide * Added deviceCapabilities has been renamed to mig guide * -chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow (#27) chore: adding CARD_PRESENT_PRIVATE_KEY to git action flow * Draft Windows SDK 3.2.5 - Added Release Notes for Windows SDK 3.2.5 - Created version Windows SDK 3.2.5 * SDK-2972 (#10) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * SDK-2972 (#29) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * SDK-2972 (#30) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Windows SDK v3.3.0 (#31) - feat: New Windows SDK 3.3.0 * Closed verison Windows SDK 3.3.0 (#32) * -feat: added DuplicateCheck to Objects and Caution admonition * - feat: closed Windows SDK 3.3.0 * Migration Guide v7 (#33) some small changes related to OperationStartResult * SDK-2972 (#34) * refactor: the name of deviceCapabilities event has been changed * Adding duplicate check flag in the REST API documentation * chore: README * chore: add version-Javascript SDK 6.2.0/javascriptmethods.md * Being more specific about duplicate_check flag * Duplicate payment check (#35) * update docs * update duplicate check documentation for all sdks * created 7.0.0 android SDK version * modified windows 3.3.0 docs with duplicate check * update Mpos to Pos * - fix: links pointing to correct section (#36) - fix: links pointing to correct site * -add: Hubspot feature (#37) -add: Hubspot feature * Fix sample code saleandtokenize method (#39) * Fix: saleAndTokenize code * fix: Method sale (setTipAmount) and finstatus table Add: Caution admonition for 7.0.0 * add: Android SDK v7.0.1 (#40) * Androidsdk v7.0.1 (#41) * add: Android SDK v7.0.1 * Added object SaleandTokenizeOptions * fix: Migration guide * feat: italian lang support (#43) * feat: italian lang support (#44) * feat: Norweian (#45) * feat: tip adjustment on REST-API (#46) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint (#47) * feat: tip adjustment on REST-API * Update restendpoints.md * fix: removed currency from request body in tip-adjustment endpoint * Update restendpoints.md * New Android SDK and REST API version (#48) Add: Android SDK 7.0.2 and REST API 2.12.0 Updated: Postman Collection for REST API with tip adjustment * Fix: Error Invalid URL's (#50) * fix: JS SDK v6.2.1 (#51) * fix: too many listeners on pusher:subscription_succeeded and pusher:subscription_error * add: JS SDK v6.2.1 (#52) * New jsversion 621 (#53) * add: JS SDK v6.2.1 * fix: folder name * feat: Metadata documentation across all SDKs (#55) * feat: Metadata documentation across all SDKs * Update androidobjects.md --------- * fix: Valid characters for Metadata (#56) * Added new Android integration info (#57) * Update: Android and REST API (#58) Upd: Android and REST API Android: Added AndroidManifest.xml info to the introduction and version updated. REST API: Updated Postman collection and printReceipt operation. * fix: js SDK v6.3.0 url and release notes (#59) * Added Release Notes for Metadata (#60) Added Release notes for Metadata Fix: Typo in Windows SDK Fix: Sample code Windows SDK * Fix: JS SDK ReleaseNotes (#61) * Add: new SDKs versions (#62) --------- * Added card reader PAX IM30 (#65) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: add static/CNAME file (#17) * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * Automate deployment (#19) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#20) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Automate deployment (#21) * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * Update deploy.yml * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * chore: testing staging deployment * fix: fixing case issues for Linux server * feat: automating deployment * chore: adding yarn.lock * fix: adding static/CNAME * fix: onBrokenLinks: 'warn' * fix: setenv.sh * fix: setenv.sh * fix: setenv.sh * WIP * WIP * WIP * WIP * WIP * WIP * chore: testing staging deployment * chore: testing staging deployment WIP * feat: migration guide android sdk v7.0.0 * feat: migration guide android sdk v7 * github comments * wip new events * added interface changes * Created new OperationStartResult Object - Add: OperationStartResult Object - Fix: Hapi operations return is now… * MISC-751 Remove Google Analytics and HubSpot tracking scripts from documentation sites (#141) * chore(docusaurus): remove Google Analytics tracking script * chore(docusaurus): remove Hubspot tracking script --------- Co-authored-by: ecunado * MISC-751 Remove subscribe link from newsletter message (#144) chore: Remove subscribe link from newsletter message Co-authored-by: ecunado --------- Co-authored-by: AlexDLL31 <114812411+alexdll31@users.noreply.github.com> Co-authored-by: Ezequiel Cuñado Co-authored-by: ecunado Co-authored-by: adrianfrez Co-authored-by: Miguel Co-authored-by: carlos Co-authored-by: Antoine Co-authored-by: cesrgzrz <52396874+cesrgzrz@users.noreply.github.com> Co-authored-by: Vicente Pavón <30615276+vicentepdj@users.noreply.github.com> Co-authored-by: Raul Carrasco Co-authored-by: ecunado